diff --git a/src/platform/graphics/webgpu/webgpu-graphics-device.js b/src/platform/graphics/webgpu/webgpu-graphics-device.js index 9893d9d9ff1..e9fa6290633 100644 --- a/src/platform/graphics/webgpu/webgpu-graphics-device.js +++ b/src/platform/graphics/webgpu/webgpu-graphics-device.js @@ -47,6 +47,15 @@ const _indirectEntryByteSize = 5 * 4; const _indirectDispatchEntryByteSize = 3 * 4; class WebgpuGraphicsDevice extends GraphicsDevice { + /** + * Array of GPU resources pending destruction. Resources are destroyed after the current + * command buffers are submitted to ensure they're not in use. + * + * @type {Array} + * @private + */ + _deferredDestroys = []; + /** * Object responsible for caching and creation of render pipelines. */ @@ -1109,6 +1118,28 @@ class WebgpuGraphicsDevice extends GraphicsDevice { // notify dynamic buffers this.dynamicBuffers.onCommandBuffersSubmitted(); } + + // destroy deferred resources after submit to ensure they're no longer referenced + const deferredDestroys = this._deferredDestroys; + if (deferredDestroys.length > 0) { + for (let i = 0; i < deferredDestroys.length; i++) { + deferredDestroys[i].destroy(); + } + deferredDestroys.length = 0; + } + } + + /** + * Defer destruction of a GPU resource until after the current command buffers are submitted. + * This ensures the resource is not destroyed while still referenced by pending GPU commands. + * + * @param {GPUTexture|GPUBuffer|GPUQuerySet} gpuResource - The GPU resource to destroy. + * @private + */ + deferDestroy(gpuResource) { + if (gpuResource) { + this._deferredDestroys.push(gpuResource); + } } clear(options) { diff --git a/src/platform/graphics/webgpu/webgpu-texture.js b/src/platform/graphics/webgpu/webgpu-texture.js index 62861226ff3..307d5c74221 100644 --- a/src/platform/graphics/webgpu/webgpu-texture.js +++ b/src/platform/graphics/webgpu/webgpu-texture.js @@ -155,7 +155,8 @@ class WebgpuTexture { } destroy(device) { - this.gpuTexture?.destroy(); + // defer GPU texture destruction until after command buffer submission + device.deferDestroy(this.gpuTexture); this.gpuTexture = null; this.view = null; this.viewCache.clear();