@luma.gl/webgpu 9.3.0-alpha.2 → 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 +31 -21
- package/dist/adapter/helpers/get-bind-group.js.map +1 -1
- package/dist/adapter/resources/webgpu-buffer.d.ts +7 -0
- package/dist/adapter/resources/webgpu-buffer.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-buffer.js +58 -15
- 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-pipeline-layout.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-pipeline-layout.js +1 -2
- package/dist/adapter/resources/webgpu-pipeline-layout.js.map +1 -1
- package/dist/adapter/resources/webgpu-query-set.d.ts +33 -4
- package/dist/adapter/resources/webgpu-query-set.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-query-set.js +145 -4
- package/dist/adapter/resources/webgpu-query-set.js.map +1 -1
- package/dist/adapter/resources/webgpu-render-pass.d.ts +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 +2864 -1702
- package/dist/dist.min.js +167 -8
- package/dist/index.cjs +1363 -225
- package/dist/index.cjs.map +4 -4
- package/package.json +5 -5
- package/src/adapter/helpers/cpu-hotspot-profiler.ts +70 -0
- package/src/adapter/helpers/generate-mipmaps-webgpu.ts +583 -0
- package/src/adapter/helpers/get-bind-group.ts +37 -22
- package/src/adapter/resources/webgpu-buffer.ts +61 -15
- 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-pipeline-layout.ts +1 -2
- 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
|
@@ -12,10 +12,13 @@ import type {
|
|
|
12
12
|
DeviceTextureFormatCapabilities,
|
|
13
13
|
VertexFormat,
|
|
14
14
|
CanvasContextProps,
|
|
15
|
+
PresentationContextProps,
|
|
16
|
+
PresentationContext,
|
|
15
17
|
BufferProps,
|
|
16
18
|
SamplerProps,
|
|
17
19
|
ShaderProps,
|
|
18
20
|
TextureProps,
|
|
21
|
+
Texture,
|
|
19
22
|
ExternalTextureProps,
|
|
20
23
|
FramebufferProps,
|
|
21
24
|
RenderPipelineProps,
|
|
@@ -41,6 +44,7 @@ import {WebGPUComputePipeline} from './resources/webgpu-compute-pipeline';
|
|
|
41
44
|
import {WebGPUVertexArray} from './resources/webgpu-vertex-array';
|
|
42
45
|
|
|
43
46
|
import {WebGPUCanvasContext} from './webgpu-canvas-context';
|
|
47
|
+
import {WebGPUPresentationContext} from './webgpu-presentation-context';
|
|
44
48
|
import {WebGPUCommandEncoder} from './resources/webgpu-command-encoder';
|
|
45
49
|
import {WebGPUCommandBuffer} from './resources/webgpu-command-buffer';
|
|
46
50
|
import {WebGPUQuerySet} from './resources/webgpu-query-set';
|
|
@@ -48,6 +52,12 @@ import {WebGPUPipelineLayout} from './resources/webgpu-pipeline-layout';
|
|
|
48
52
|
import {WebGPUFence} from './resources/webgpu-fence';
|
|
49
53
|
|
|
50
54
|
import {getShaderLayoutFromWGSL} from '../wgsl/get-shader-layout-wgsl';
|
|
55
|
+
import {generateMipmapsWebGPU} from './helpers/generate-mipmaps-webgpu';
|
|
56
|
+
import {
|
|
57
|
+
getCpuHotspotProfiler as getWebGPUCpuHotspotProfiler,
|
|
58
|
+
getCpuHotspotSubmitReason as getWebGPUCpuHotspotSubmitReason,
|
|
59
|
+
getTimestamp
|
|
60
|
+
} from './helpers/cpu-hotspot-profiler';
|
|
51
61
|
|
|
52
62
|
/** WebGPU Device implementation */
|
|
53
63
|
export class WebGPUDevice extends Device {
|
|
@@ -75,6 +85,7 @@ export class WebGPUDevice extends Device {
|
|
|
75
85
|
override canvasContext: WebGPUCanvasContext | null = null;
|
|
76
86
|
|
|
77
87
|
private _isLost: boolean = false;
|
|
88
|
+
private _defaultSampler: WebGPUSampler | null = null;
|
|
78
89
|
commandEncoder: WebGPUCommandEncoder;
|
|
79
90
|
|
|
80
91
|
override get [Symbol.toStringTag](): string {
|
|
@@ -132,6 +143,9 @@ export class WebGPUDevice extends Device {
|
|
|
132
143
|
// this.glslang = glsl && await loadGlslangModule();
|
|
133
144
|
|
|
134
145
|
destroy(): void {
|
|
146
|
+
this.commandEncoder?.destroy();
|
|
147
|
+
this._defaultSampler?.destroy();
|
|
148
|
+
this._defaultSampler = null;
|
|
135
149
|
this.handle.destroy();
|
|
136
150
|
}
|
|
137
151
|
|
|
@@ -169,6 +183,13 @@ export class WebGPUDevice extends Device {
|
|
|
169
183
|
return new WebGPUSampler(this, props);
|
|
170
184
|
}
|
|
171
185
|
|
|
186
|
+
getDefaultSampler(): WebGPUSampler {
|
|
187
|
+
this._defaultSampler ||= new WebGPUSampler(this, {
|
|
188
|
+
id: `${this.id}-default-sampler`
|
|
189
|
+
});
|
|
190
|
+
return this._defaultSampler;
|
|
191
|
+
}
|
|
192
|
+
|
|
172
193
|
createRenderPipeline(props: RenderPipelineProps): WebGPURenderPipeline {
|
|
173
194
|
return new WebGPURenderPipeline(this, props);
|
|
174
195
|
}
|
|
@@ -207,37 +228,126 @@ export class WebGPUDevice extends Device {
|
|
|
207
228
|
return new WebGPUCanvasContext(this, this.adapter, props);
|
|
208
229
|
}
|
|
209
230
|
|
|
231
|
+
createPresentationContext(props?: PresentationContextProps): PresentationContext {
|
|
232
|
+
return new WebGPUPresentationContext(this, props);
|
|
233
|
+
}
|
|
234
|
+
|
|
210
235
|
createPipelineLayout(props: PipelineLayoutProps): WebGPUPipelineLayout {
|
|
211
236
|
return new WebGPUPipelineLayout(this, props);
|
|
212
237
|
}
|
|
213
238
|
|
|
239
|
+
override generateMipmapsWebGPU(texture: Texture): void {
|
|
240
|
+
generateMipmapsWebGPU(this, texture);
|
|
241
|
+
}
|
|
242
|
+
|
|
214
243
|
submit(commandBuffer?: WebGPUCommandBuffer): void {
|
|
244
|
+
let submittedCommandEncoder: WebGPUCommandEncoder | null = null;
|
|
215
245
|
if (!commandBuffer) {
|
|
216
|
-
|
|
246
|
+
submittedCommandEncoder = this.commandEncoder;
|
|
247
|
+
if (
|
|
248
|
+
submittedCommandEncoder.getTimeProfilingSlotCount() > 0 &&
|
|
249
|
+
submittedCommandEncoder.getTimeProfilingQuerySet() instanceof WebGPUQuerySet
|
|
250
|
+
) {
|
|
251
|
+
const querySet = submittedCommandEncoder.getTimeProfilingQuerySet() as WebGPUQuerySet;
|
|
252
|
+
querySet._encodeResolveToReadBuffer(submittedCommandEncoder, {
|
|
253
|
+
firstQuery: 0,
|
|
254
|
+
queryCount: submittedCommandEncoder.getTimeProfilingSlotCount()
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
commandBuffer = submittedCommandEncoder.finish();
|
|
217
258
|
this.commandEncoder.destroy();
|
|
218
|
-
this.commandEncoder = this.createCommandEncoder({
|
|
259
|
+
this.commandEncoder = this.createCommandEncoder({
|
|
260
|
+
id: submittedCommandEncoder.props.id,
|
|
261
|
+
timeProfilingQuerySet: submittedCommandEncoder.getTimeProfilingQuerySet()
|
|
262
|
+
});
|
|
219
263
|
}
|
|
220
264
|
|
|
221
|
-
this
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
this.
|
|
226
|
-
|
|
265
|
+
const profiler = getWebGPUCpuHotspotProfiler(this);
|
|
266
|
+
const startTime = profiler ? getTimestamp() : 0;
|
|
267
|
+
const submitReason = getWebGPUCpuHotspotSubmitReason(this);
|
|
268
|
+
try {
|
|
269
|
+
this.pushErrorScope('validation');
|
|
270
|
+
const queueSubmitStartTime = profiler ? getTimestamp() : 0;
|
|
271
|
+
this.handle.queue.submit([commandBuffer.handle]);
|
|
272
|
+
if (profiler) {
|
|
273
|
+
profiler.queueSubmitCount = (profiler.queueSubmitCount || 0) + 1;
|
|
274
|
+
profiler.queueSubmitTimeMs =
|
|
275
|
+
(profiler.queueSubmitTimeMs || 0) + (getTimestamp() - queueSubmitStartTime);
|
|
276
|
+
}
|
|
277
|
+
this.popErrorScope((error: GPUError) => {
|
|
278
|
+
this.reportError(new Error(`${this} command submission: ${error.message}`), this)();
|
|
279
|
+
this.debug();
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
if (submittedCommandEncoder) {
|
|
283
|
+
const submitResolveKickoffStartTime = profiler ? getTimestamp() : 0;
|
|
284
|
+
scheduleMicrotask(() => {
|
|
285
|
+
submittedCommandEncoder
|
|
286
|
+
.resolveTimeProfilingQuerySet()
|
|
287
|
+
.then(() => {
|
|
288
|
+
this.commandEncoder._gpuTimeMs = submittedCommandEncoder._gpuTimeMs;
|
|
289
|
+
})
|
|
290
|
+
.catch(() => {});
|
|
291
|
+
});
|
|
292
|
+
if (profiler) {
|
|
293
|
+
profiler.submitResolveKickoffCount = (profiler.submitResolveKickoffCount || 0) + 1;
|
|
294
|
+
profiler.submitResolveKickoffTimeMs =
|
|
295
|
+
(profiler.submitResolveKickoffTimeMs || 0) +
|
|
296
|
+
(getTimestamp() - submitResolveKickoffStartTime);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
} finally {
|
|
300
|
+
if (profiler) {
|
|
301
|
+
profiler.submitCount = (profiler.submitCount || 0) + 1;
|
|
302
|
+
profiler.submitTimeMs = (profiler.submitTimeMs || 0) + (getTimestamp() - startTime);
|
|
303
|
+
const reasonCountKey =
|
|
304
|
+
submitReason === 'query-readback' ? 'queryReadbackSubmitCount' : 'defaultSubmitCount';
|
|
305
|
+
const reasonTimeKey =
|
|
306
|
+
submitReason === 'query-readback' ? 'queryReadbackSubmitTimeMs' : 'defaultSubmitTimeMs';
|
|
307
|
+
profiler[reasonCountKey] = (profiler[reasonCountKey] || 0) + 1;
|
|
308
|
+
profiler[reasonTimeKey] = (profiler[reasonTimeKey] || 0) + (getTimestamp() - startTime);
|
|
309
|
+
}
|
|
310
|
+
const commandBufferDestroyStartTime = profiler ? getTimestamp() : 0;
|
|
311
|
+
commandBuffer.destroy();
|
|
312
|
+
if (profiler) {
|
|
313
|
+
profiler.commandBufferDestroyCount = (profiler.commandBufferDestroyCount || 0) + 1;
|
|
314
|
+
profiler.commandBufferDestroyTimeMs =
|
|
315
|
+
(profiler.commandBufferDestroyTimeMs || 0) +
|
|
316
|
+
(getTimestamp() - commandBufferDestroyStartTime);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
227
319
|
}
|
|
228
320
|
|
|
229
321
|
// WebGPU specific
|
|
230
322
|
|
|
231
323
|
pushErrorScope(scope: 'validation' | 'out-of-memory'): void {
|
|
324
|
+
if (!this.props.debug) {
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
const profiler = getWebGPUCpuHotspotProfiler(this);
|
|
328
|
+
const startTime = profiler ? getTimestamp() : 0;
|
|
232
329
|
this.handle.pushErrorScope(scope);
|
|
330
|
+
if (profiler) {
|
|
331
|
+
profiler.errorScopePushCount = (profiler.errorScopePushCount || 0) + 1;
|
|
332
|
+
profiler.errorScopeTimeMs = (profiler.errorScopeTimeMs || 0) + (getTimestamp() - startTime);
|
|
333
|
+
}
|
|
233
334
|
}
|
|
234
335
|
|
|
235
336
|
popErrorScope(handler: (error: GPUError) => void): void {
|
|
337
|
+
if (!this.props.debug) {
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
const profiler = getWebGPUCpuHotspotProfiler(this);
|
|
341
|
+
const startTime = profiler ? getTimestamp() : 0;
|
|
236
342
|
this.handle.popErrorScope().then((error: GPUError | null) => {
|
|
237
343
|
if (error) {
|
|
238
344
|
handler(error);
|
|
239
345
|
}
|
|
240
346
|
});
|
|
347
|
+
if (profiler) {
|
|
348
|
+
profiler.errorScopePopCount = (profiler.errorScopePopCount || 0) + 1;
|
|
349
|
+
profiler.errorScopeTimeMs = (profiler.errorScopeTimeMs || 0) + (getTimestamp() - startTime);
|
|
350
|
+
}
|
|
241
351
|
}
|
|
242
352
|
|
|
243
353
|
// PRIVATE METHODS
|
|
@@ -294,7 +404,6 @@ export class WebGPUDevice extends Device {
|
|
|
294
404
|
}
|
|
295
405
|
|
|
296
406
|
const WEBGPU_ALWAYS_FEATURES: DeviceFeature[] = [
|
|
297
|
-
'timer-query-webgl',
|
|
298
407
|
'compilation-status-async-webgl',
|
|
299
408
|
'float32-renderable-webgl',
|
|
300
409
|
'float16-renderable-webgl',
|
|
@@ -320,3 +429,13 @@ export class WebGPUDevice extends Device {
|
|
|
320
429
|
return capabilities;
|
|
321
430
|
}
|
|
322
431
|
}
|
|
432
|
+
|
|
433
|
+
function scheduleMicrotask(callback: () => void): void {
|
|
434
|
+
if (globalThis.queueMicrotask) {
|
|
435
|
+
globalThis.queueMicrotask(callback);
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
Promise.resolve()
|
|
439
|
+
.then(callback)
|
|
440
|
+
.catch(() => {});
|
|
441
|
+
}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
// luma.gl
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
// Copyright (c) vis.gl contributors
|
|
4
|
+
|
|
5
|
+
// prettier-ignore
|
|
6
|
+
// / <reference types="@webgpu/types" />
|
|
7
|
+
|
|
8
|
+
import type {PresentationContextProps, TextureFormatDepthStencil} from '@luma.gl/core';
|
|
9
|
+
import {PresentationContext, Texture, log} from '@luma.gl/core';
|
|
10
|
+
import type {WebGPUDevice} from './webgpu-device';
|
|
11
|
+
import {WebGPUFramebuffer} from './resources/webgpu-framebuffer';
|
|
12
|
+
import {WebGPUTexture} from './resources/webgpu-texture';
|
|
13
|
+
import {getCpuHotspotProfiler, getTimestamp} from './helpers/cpu-hotspot-profiler';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* A WebGPU PresentationContext renders directly into its destination canvas.
|
|
17
|
+
*/
|
|
18
|
+
export class WebGPUPresentationContext extends PresentationContext {
|
|
19
|
+
readonly device: WebGPUDevice;
|
|
20
|
+
readonly handle: GPUCanvasContext;
|
|
21
|
+
|
|
22
|
+
private colorAttachment: WebGPUTexture | null = null;
|
|
23
|
+
private depthStencilAttachment: WebGPUTexture | null = null;
|
|
24
|
+
private framebuffer: WebGPUFramebuffer | null = null;
|
|
25
|
+
|
|
26
|
+
get [Symbol.toStringTag](): string {
|
|
27
|
+
return 'WebGPUPresentationContext';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
constructor(device: WebGPUDevice, props: PresentationContextProps = {}) {
|
|
31
|
+
super(props);
|
|
32
|
+
const contextLabel = `${this[Symbol.toStringTag]}(${this.id})`;
|
|
33
|
+
|
|
34
|
+
const context = this.canvas.getContext('webgpu');
|
|
35
|
+
if (!context) {
|
|
36
|
+
throw new Error(`${contextLabel}: Failed to create WebGPU presentation context`);
|
|
37
|
+
}
|
|
38
|
+
this.device = device;
|
|
39
|
+
this.handle = context;
|
|
40
|
+
|
|
41
|
+
this._setAutoCreatedCanvasId(`${this.device.id}-presentation-canvas`);
|
|
42
|
+
this._configureDevice();
|
|
43
|
+
this._startObservers();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
override destroy(): void {
|
|
47
|
+
if (this.framebuffer) {
|
|
48
|
+
this.framebuffer.destroy();
|
|
49
|
+
this.framebuffer = null;
|
|
50
|
+
}
|
|
51
|
+
if (this.colorAttachment) {
|
|
52
|
+
this.colorAttachment.destroy();
|
|
53
|
+
this.colorAttachment = null;
|
|
54
|
+
}
|
|
55
|
+
if (this.depthStencilAttachment) {
|
|
56
|
+
this.depthStencilAttachment.destroy();
|
|
57
|
+
this.depthStencilAttachment = null;
|
|
58
|
+
}
|
|
59
|
+
this.handle.unconfigure();
|
|
60
|
+
super.destroy();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
present(): void {
|
|
64
|
+
this.device.submit();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
protected override _configureDevice(): void {
|
|
68
|
+
if (this.depthStencilAttachment) {
|
|
69
|
+
this.depthStencilAttachment.destroy();
|
|
70
|
+
this.depthStencilAttachment = null;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
this.handle.configure({
|
|
74
|
+
device: this.device.handle,
|
|
75
|
+
format: this.device.preferredColorFormat,
|
|
76
|
+
colorSpace: this.props.colorSpace,
|
|
77
|
+
alphaMode: this.props.alphaMode
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
this._createDepthStencilAttachment(this.device.preferredDepthFormat);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
protected override _getCurrentFramebuffer(
|
|
84
|
+
options: {depthStencilFormat?: TextureFormatDepthStencil | false} = {
|
|
85
|
+
depthStencilFormat: 'depth24plus'
|
|
86
|
+
}
|
|
87
|
+
): WebGPUFramebuffer {
|
|
88
|
+
const profiler = getCpuHotspotProfiler(this.device);
|
|
89
|
+
const startTime = profiler ? getTimestamp() : 0;
|
|
90
|
+
if (profiler) {
|
|
91
|
+
profiler.framebufferAcquireCount = (profiler.framebufferAcquireCount || 0) + 1;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
try {
|
|
95
|
+
const currentColorAttachment = this._getCurrentTexture();
|
|
96
|
+
if (
|
|
97
|
+
currentColorAttachment.width !== this.drawingBufferWidth ||
|
|
98
|
+
currentColorAttachment.height !== this.drawingBufferHeight
|
|
99
|
+
) {
|
|
100
|
+
const [oldWidth, oldHeight] = this.getDrawingBufferSize();
|
|
101
|
+
this.drawingBufferWidth = currentColorAttachment.width;
|
|
102
|
+
this.drawingBufferHeight = currentColorAttachment.height;
|
|
103
|
+
log.log(
|
|
104
|
+
1,
|
|
105
|
+
`${this[Symbol.toStringTag]}(${this.id}): Resized to compensate for initial canvas size mismatch ${oldWidth}x${oldHeight} => ${this.drawingBufferWidth}x${this.drawingBufferHeight}px`
|
|
106
|
+
)();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (options?.depthStencilFormat) {
|
|
110
|
+
this._createDepthStencilAttachment(options.depthStencilFormat);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
this.framebuffer ||= new WebGPUFramebuffer(this.device, {
|
|
114
|
+
id: `${this.id}#framebuffer`,
|
|
115
|
+
colorAttachments: [currentColorAttachment],
|
|
116
|
+
depthStencilAttachment: null
|
|
117
|
+
});
|
|
118
|
+
this.framebuffer._reinitialize(
|
|
119
|
+
currentColorAttachment.view,
|
|
120
|
+
options?.depthStencilFormat ? this.depthStencilAttachment?.view || null : null
|
|
121
|
+
);
|
|
122
|
+
return this.framebuffer;
|
|
123
|
+
} finally {
|
|
124
|
+
if (profiler) {
|
|
125
|
+
profiler.framebufferAcquireTimeMs =
|
|
126
|
+
(profiler.framebufferAcquireTimeMs || 0) + (getTimestamp() - startTime);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
private _getCurrentTexture(): WebGPUTexture {
|
|
132
|
+
const profiler = getCpuHotspotProfiler(this.device);
|
|
133
|
+
const currentTextureStartTime = profiler ? getTimestamp() : 0;
|
|
134
|
+
const handle = this.handle.getCurrentTexture();
|
|
135
|
+
if (profiler) {
|
|
136
|
+
profiler.currentTextureAcquireCount = (profiler.currentTextureAcquireCount || 0) + 1;
|
|
137
|
+
profiler.currentTextureAcquireTimeMs =
|
|
138
|
+
(profiler.currentTextureAcquireTimeMs || 0) + (getTimestamp() - currentTextureStartTime);
|
|
139
|
+
}
|
|
140
|
+
if (!this.colorAttachment) {
|
|
141
|
+
this.colorAttachment = this.device.createTexture({
|
|
142
|
+
id: `${this.id}#color-texture`,
|
|
143
|
+
handle,
|
|
144
|
+
format: this.device.preferredColorFormat,
|
|
145
|
+
width: handle.width,
|
|
146
|
+
height: handle.height
|
|
147
|
+
});
|
|
148
|
+
return this.colorAttachment;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
this.colorAttachment._reinitialize(handle, {
|
|
152
|
+
handle,
|
|
153
|
+
format: this.device.preferredColorFormat,
|
|
154
|
+
width: handle.width,
|
|
155
|
+
height: handle.height
|
|
156
|
+
});
|
|
157
|
+
return this.colorAttachment;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
private _createDepthStencilAttachment(
|
|
161
|
+
depthStencilFormat: TextureFormatDepthStencil
|
|
162
|
+
): WebGPUTexture {
|
|
163
|
+
const needsNewDepthStencilAttachment =
|
|
164
|
+
!this.depthStencilAttachment ||
|
|
165
|
+
this.depthStencilAttachment.width !== this.drawingBufferWidth ||
|
|
166
|
+
this.depthStencilAttachment.height !== this.drawingBufferHeight ||
|
|
167
|
+
this.depthStencilAttachment.format !== depthStencilFormat;
|
|
168
|
+
if (needsNewDepthStencilAttachment) {
|
|
169
|
+
this.depthStencilAttachment?.destroy();
|
|
170
|
+
this.depthStencilAttachment = this.device.createTexture({
|
|
171
|
+
id: `${this.id}#depth-stencil-texture`,
|
|
172
|
+
usage: Texture.RENDER_ATTACHMENT,
|
|
173
|
+
format: depthStencilFormat,
|
|
174
|
+
width: this.drawingBufferWidth,
|
|
175
|
+
height: this.drawingBufferHeight
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
return this.depthStencilAttachment!;
|
|
179
|
+
}
|
|
180
|
+
}
|