@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.
Files changed (98) hide show
  1. package/dist/adapter/helpers/cpu-hotspot-profiler.d.ts +54 -0
  2. package/dist/adapter/helpers/cpu-hotspot-profiler.d.ts.map +1 -0
  3. package/dist/adapter/helpers/cpu-hotspot-profiler.js +26 -0
  4. package/dist/adapter/helpers/cpu-hotspot-profiler.js.map +1 -0
  5. package/dist/adapter/helpers/generate-mipmaps-webgpu.d.ts +7 -0
  6. package/dist/adapter/helpers/generate-mipmaps-webgpu.d.ts.map +1 -0
  7. package/dist/adapter/helpers/generate-mipmaps-webgpu.js +490 -0
  8. package/dist/adapter/helpers/generate-mipmaps-webgpu.js.map +1 -0
  9. package/dist/adapter/helpers/get-bind-group.d.ts +2 -1
  10. package/dist/adapter/helpers/get-bind-group.d.ts.map +1 -1
  11. package/dist/adapter/helpers/get-bind-group.js +31 -21
  12. package/dist/adapter/helpers/get-bind-group.js.map +1 -1
  13. package/dist/adapter/resources/webgpu-buffer.d.ts +7 -0
  14. package/dist/adapter/resources/webgpu-buffer.d.ts.map +1 -1
  15. package/dist/adapter/resources/webgpu-buffer.js +58 -15
  16. package/dist/adapter/resources/webgpu-buffer.js.map +1 -1
  17. package/dist/adapter/resources/webgpu-command-buffer.js +1 -1
  18. package/dist/adapter/resources/webgpu-command-buffer.js.map +1 -1
  19. package/dist/adapter/resources/webgpu-command-encoder.d.ts +5 -4
  20. package/dist/adapter/resources/webgpu-command-encoder.d.ts.map +1 -1
  21. package/dist/adapter/resources/webgpu-command-encoder.js +23 -5
  22. package/dist/adapter/resources/webgpu-command-encoder.js.map +1 -1
  23. package/dist/adapter/resources/webgpu-compute-pass.d.ts +1 -1
  24. package/dist/adapter/resources/webgpu-compute-pass.d.ts.map +1 -1
  25. package/dist/adapter/resources/webgpu-compute-pass.js +14 -6
  26. package/dist/adapter/resources/webgpu-compute-pass.js.map +1 -1
  27. package/dist/adapter/resources/webgpu-compute-pipeline.d.ts.map +1 -1
  28. package/dist/adapter/resources/webgpu-compute-pipeline.js +19 -3
  29. package/dist/adapter/resources/webgpu-compute-pipeline.js.map +1 -1
  30. package/dist/adapter/resources/webgpu-framebuffer.d.ts +6 -0
  31. package/dist/adapter/resources/webgpu-framebuffer.d.ts.map +1 -1
  32. package/dist/adapter/resources/webgpu-framebuffer.js +16 -0
  33. package/dist/adapter/resources/webgpu-framebuffer.js.map +1 -1
  34. package/dist/adapter/resources/webgpu-pipeline-layout.d.ts.map +1 -1
  35. package/dist/adapter/resources/webgpu-pipeline-layout.js +1 -2
  36. package/dist/adapter/resources/webgpu-pipeline-layout.js.map +1 -1
  37. package/dist/adapter/resources/webgpu-query-set.d.ts +33 -4
  38. package/dist/adapter/resources/webgpu-query-set.d.ts.map +1 -1
  39. package/dist/adapter/resources/webgpu-query-set.js +145 -4
  40. package/dist/adapter/resources/webgpu-query-set.js.map +1 -1
  41. package/dist/adapter/resources/webgpu-render-pass.d.ts +3 -0
  42. package/dist/adapter/resources/webgpu-render-pass.d.ts.map +1 -1
  43. package/dist/adapter/resources/webgpu-render-pass.js +74 -30
  44. package/dist/adapter/resources/webgpu-render-pass.js.map +1 -1
  45. package/dist/adapter/resources/webgpu-render-pipeline.d.ts +7 -4
  46. package/dist/adapter/resources/webgpu-render-pipeline.d.ts.map +1 -1
  47. package/dist/adapter/resources/webgpu-render-pipeline.js +26 -15
  48. package/dist/adapter/resources/webgpu-render-pipeline.js.map +1 -1
  49. package/dist/adapter/resources/webgpu-sampler.d.ts.map +1 -1
  50. package/dist/adapter/resources/webgpu-sampler.js +4 -0
  51. package/dist/adapter/resources/webgpu-sampler.js.map +1 -1
  52. package/dist/adapter/resources/webgpu-texture-view.d.ts +6 -0
  53. package/dist/adapter/resources/webgpu-texture-view.d.ts.map +1 -1
  54. package/dist/adapter/resources/webgpu-texture-view.js +47 -11
  55. package/dist/adapter/resources/webgpu-texture-view.js.map +1 -1
  56. package/dist/adapter/resources/webgpu-texture.d.ts +10 -4
  57. package/dist/adapter/resources/webgpu-texture.d.ts.map +1 -1
  58. package/dist/adapter/resources/webgpu-texture.js +116 -57
  59. package/dist/adapter/resources/webgpu-texture.js.map +1 -1
  60. package/dist/adapter/resources/webgpu-vertex-array.js +1 -1
  61. package/dist/adapter/resources/webgpu-vertex-array.js.map +1 -1
  62. package/dist/adapter/webgpu-canvas-context.d.ts +2 -0
  63. package/dist/adapter/webgpu-canvas-context.d.ts.map +1 -1
  64. package/dist/adapter/webgpu-canvas-context.js +78 -19
  65. package/dist/adapter/webgpu-canvas-context.js.map +1 -1
  66. package/dist/adapter/webgpu-device.d.ts +5 -1
  67. package/dist/adapter/webgpu-device.d.ts.map +1 -1
  68. package/dist/adapter/webgpu-device.js +113 -9
  69. package/dist/adapter/webgpu-device.js.map +1 -1
  70. package/dist/adapter/webgpu-presentation-context.d.ts +25 -0
  71. package/dist/adapter/webgpu-presentation-context.d.ts.map +1 -0
  72. package/dist/adapter/webgpu-presentation-context.js +144 -0
  73. package/dist/adapter/webgpu-presentation-context.js.map +1 -0
  74. package/dist/dist.dev.js +2864 -1702
  75. package/dist/dist.min.js +167 -8
  76. package/dist/index.cjs +1363 -225
  77. package/dist/index.cjs.map +4 -4
  78. package/package.json +5 -5
  79. package/src/adapter/helpers/cpu-hotspot-profiler.ts +70 -0
  80. package/src/adapter/helpers/generate-mipmaps-webgpu.ts +583 -0
  81. package/src/adapter/helpers/get-bind-group.ts +37 -22
  82. package/src/adapter/resources/webgpu-buffer.ts +61 -15
  83. package/src/adapter/resources/webgpu-command-buffer.ts +1 -1
  84. package/src/adapter/resources/webgpu-command-encoder.ts +32 -6
  85. package/src/adapter/resources/webgpu-compute-pass.ts +14 -6
  86. package/src/adapter/resources/webgpu-compute-pipeline.ts +21 -3
  87. package/src/adapter/resources/webgpu-framebuffer.ts +21 -0
  88. package/src/adapter/resources/webgpu-pipeline-layout.ts +1 -2
  89. package/src/adapter/resources/webgpu-query-set.ts +185 -9
  90. package/src/adapter/resources/webgpu-render-pass.ts +82 -34
  91. package/src/adapter/resources/webgpu-render-pipeline.ts +36 -19
  92. package/src/adapter/resources/webgpu-sampler.ts +5 -0
  93. package/src/adapter/resources/webgpu-texture-view.ts +51 -11
  94. package/src/adapter/resources/webgpu-texture.ts +142 -93
  95. package/src/adapter/resources/webgpu-vertex-array.ts +1 -1
  96. package/src/adapter/webgpu-canvas-context.ts +91 -26
  97. package/src/adapter/webgpu-device.ts +128 -9
  98. 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
- commandBuffer = this.commandEncoder.finish();
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({id: `${this.id}-default-encoder`});
259
+ this.commandEncoder = this.createCommandEncoder({
260
+ id: submittedCommandEncoder.props.id,
261
+ timeProfilingQuerySet: submittedCommandEncoder.getTimeProfilingQuerySet()
262
+ });
219
263
  }
220
264
 
221
- this.pushErrorScope('validation');
222
- this.handle.queue.submit([commandBuffer.handle]);
223
- this.popErrorScope((error: GPUError) => {
224
- this.reportError(new Error(`${this} command submission: ${error.message}`), this)();
225
- this.debug();
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
+ }