diff --git a/src/platform/graphics/webgpu/webgpu-graphics-device.js b/src/platform/graphics/webgpu/webgpu-graphics-device.js index fe8d11a2848..b3b01355c09 100644 --- a/src/platform/graphics/webgpu/webgpu-graphics-device.js +++ b/src/platform/graphics/webgpu/webgpu-graphics-device.js @@ -702,10 +702,6 @@ class WebgpuGraphicsDevice extends GraphicsDevice { /** @type {WebgpuRenderTarget} */ const wrt = rt.impl; - // create a new encoder for each pass - this.commandEncoder = this.wgpu.createCommandEncoder(); - DebugHelper.setLabel(this.commandEncoder, `${renderPass.name}-CommandEncoder RT:${rt.name}`); - // framebuffer is initialized at the start of the frame if (rt !== this.backBuffer) { this.initRenderTarget(rt); @@ -720,7 +716,8 @@ class WebgpuGraphicsDevice extends GraphicsDevice { this.setupTimeStampWrites(renderPassDesc, renderPass.name); // start the pass - this.passEncoder = this.commandEncoder.beginRenderPass(renderPassDesc); + const commandEncoder = this.getCommandEncoder(); + this.passEncoder = commandEncoder.beginRenderPass(renderPassDesc); this.passEncoder.label = `${renderPass.name}-PassEncoder RT:${rt.name}`; // push marker to the passEncoder @@ -782,13 +779,6 @@ class WebgpuGraphicsDevice extends GraphicsDevice { } } - // schedule command buffer submission - const cb = this.commandEncoder.finish(); - DebugHelper.setLabel(cb, `${renderPass.name}-CommandBuffer`); - - this.addCommandBuffer(cb); - this.commandEncoder = null; - WebgpuDebug.end(this, { renderPass }); WebgpuDebug.end(this, { renderPass }); } @@ -798,10 +788,6 @@ class WebgpuGraphicsDevice extends GraphicsDevice { WebgpuDebug.internal(this); WebgpuDebug.validate(this); - // create a new encoder for each pass - this.commandEncoder = this.wgpu.createCommandEncoder(); - DebugHelper.setLabel(this.commandEncoder, `${name}-ComputePass-Encoder`); - // clear cached encoder state this.pipeline = null; @@ -809,7 +795,8 @@ class WebgpuGraphicsDevice extends GraphicsDevice { const computePassDesc = this.setupTimeStampWrites(undefined, name); // start the pass - this.passEncoder = this.commandEncoder.beginComputePass(computePassDesc); + const commandEncoder = this.getCommandEncoder(); + this.passEncoder = commandEncoder.beginComputePass(computePassDesc); DebugHelper.setLabel(this.passEncoder, `ComputePass-${name}`); Debug.assert(!this.insideRenderPass, 'ComputePass cannot be started while inside another pass.'); @@ -826,14 +813,6 @@ class WebgpuGraphicsDevice extends GraphicsDevice { // each render pass can use different number of bind groups this.bindGroupFormats.length = 0; - // schedule command buffer submission - const cb = this.commandEncoder.finish(); - // DebugHelper.setLabel(cb, `${renderPass.name}-CommandBuffer`); - DebugHelper.setLabel(cb, 'ComputePass-CommandBuffer'); - - this.addCommandBuffer(cb); - this.commandEncoder = null; - WebgpuDebug.end(this); WebgpuDebug.end(this); } @@ -858,6 +837,33 @@ class WebgpuGraphicsDevice extends GraphicsDevice { this.endComputePass(); } + getCommandEncoder() { + + // use existing or create new encoder + let commandEncoder = this.commandEncoder; + if (!commandEncoder) { + commandEncoder = this.wgpu.createCommandEncoder(); + DebugHelper.setLabel(commandEncoder, 'CommandEncoder-Shared'); + + this.commandEncoder = commandEncoder; + } + + return commandEncoder; + } + + endCommandEncoder() { + + const { commandEncoder } = this; + if (commandEncoder) { + + const cb = commandEncoder.finish(); + DebugHelper.setLabel(cb, 'CommandBuffer-Shared'); + + this.addCommandBuffer(cb); + this.commandEncoder = null; + } + } + addCommandBuffer(commandBuffer, front = false) { if (front) { this.commandBuffers.unshift(commandBuffer); @@ -867,6 +873,10 @@ class WebgpuGraphicsDevice extends GraphicsDevice { } submit() { + + // end the current encoder + this.endCommandEncoder(); + if (this.commandBuffers.length > 0) { // copy dynamic buffers data to the GPU (this schedules the copy CB to run before all other CBs) @@ -944,18 +954,8 @@ class WebgpuGraphicsDevice extends GraphicsDevice { */ clearStorageBuffer(storageBuffer, offset = 0, size = storageBuffer.byteSize) { - // use existing or create new encoder - const commandEncoder = this.commandEncoder ?? this.wgpu.createCommandEncoder(); - + const commandEncoder = this.getCommandEncoder(); commandEncoder.clearBuffer(storageBuffer.buffer, offset, size); - - // if we created the encoder - if (!this.commandEncoder) { - DebugHelper.setLabel(commandEncoder, 'ReadStorageBuffer-Encoder'); - const cb = commandEncoder.finish(); - DebugHelper.setLabel(cb, 'ReadStorageBuffer-CommandBuffer'); - this.addCommandBuffer(cb); - } } /** @@ -983,20 +983,10 @@ class WebgpuGraphicsDevice extends GraphicsDevice { stagingBuffer.allocate(this, size); const destBuffer = stagingBuffer.buffer; - // use existing or create new encoder - const commandEncoder = this.commandEncoder ?? this.wgpu.createCommandEncoder(); - // copy the GPU buffer to the staging buffer + const commandEncoder = this.getCommandEncoder(); commandEncoder.copyBufferToBuffer(storageBuffer.buffer, offset, destBuffer, 0, size); - // if we created new encoder - if (!this.commandEncoder) { - DebugHelper.setLabel(commandEncoder, 'ReadStorageBuffer-Encoder'); - const cb = commandEncoder.finish(); - DebugHelper.setLabel(cb, 'ReadStorageBuffer-CommandBuffer'); - this.addCommandBuffer(cb); - } - return this.readBuffer(stagingBuffer, size, data, immediate); } @@ -1075,8 +1065,7 @@ class WebgpuGraphicsDevice extends GraphicsDevice { depthOrArrayLayers: 1 }; - // use existing or create new encoder if not in a render pass - const commandEncoder = this.commandEncoder ?? this.wgpu.createCommandEncoder(); + const commandEncoder = this.getCommandEncoder(); DebugGraphics.pushGpuMarker(this, 'COPY-RT'); @@ -1136,17 +1125,6 @@ class WebgpuGraphicsDevice extends GraphicsDevice { DebugGraphics.popGpuMarker(this); - // if we created the encoder - if (!this.commandEncoder) { - - DebugHelper.setLabel(commandEncoder, 'CopyRenderTarget-Encoder'); - - // copy operation runs next - const cb = commandEncoder.finish(); - DebugHelper.setLabel(cb, 'CopyRenderTarget-CommandBuffer'); - this.addCommandBuffer(cb); - } - return true; } diff --git a/src/platform/graphics/webgpu/webgpu-mipmap-renderer.js b/src/platform/graphics/webgpu/webgpu-mipmap-renderer.js index 7fbcf6521e9..67cd14e1c00 100644 --- a/src/platform/graphics/webgpu/webgpu-mipmap-renderer.js +++ b/src/platform/graphics/webgpu/webgpu-mipmap-renderer.js @@ -123,8 +123,7 @@ class WebgpuMipmapRenderer { } // loop through each mip level and render the previous level's contents into it. - const commandEncoder = device.commandEncoder ?? wgpu.createCommandEncoder(); - DebugHelper.setLabel(commandEncoder, 'MipmapRendererEncoder'); + const commandEncoder = device.getCommandEncoder(); DebugGraphics.pushGpuMarker(device, 'MIPMAP-RENDERER'); @@ -171,14 +170,6 @@ class WebgpuMipmapRenderer { DebugGraphics.popGpuMarker(device); - // submit the encoded commands if we created the encoder - if (!device.commandEncoder) { - - const cb = commandEncoder.finish(); - DebugHelper.setLabel(cb, 'MipmapRenderer-CommandBuffer'); - device.addCommandBuffer(cb); - } - // clear invalidated state device.pipeline = null; } diff --git a/src/platform/graphics/webgpu/webgpu-query-set.js b/src/platform/graphics/webgpu/webgpu-query-set.js index 4bde8168f51..ef9978b366d 100644 --- a/src/platform/graphics/webgpu/webgpu-query-set.js +++ b/src/platform/graphics/webgpu/webgpu-query-set.js @@ -68,8 +68,7 @@ class WebgpuQuerySet { resolve(count) { const device = this.device; - const commandEncoder = device.wgpu.createCommandEncoder(); - DebugHelper.setLabel(commandEncoder, 'ResolveQuerySet-Encoder'); + const commandEncoder = device.getCommandEncoder(); // copy times to the gpu buffer commandEncoder.resolveQuerySet(this.querySet, 0, count, this.queryBuffer, 0); @@ -79,10 +78,6 @@ class WebgpuQuerySet { this.activeStagingBuffer = activeStagingBuffer; commandEncoder.copyBufferToBuffer(this.queryBuffer, 0, activeStagingBuffer, 0, this.bytesPerSlot * count); - - const cb = commandEncoder.finish(); - DebugHelper.setLabel(cb, 'ResolveQuerySet'); - device.addCommandBuffer(cb); } request(count, renderVersion) { diff --git a/src/platform/graphics/webgpu/webgpu-texture.js b/src/platform/graphics/webgpu/webgpu-texture.js index 63f363bcb88..d6063ad6ae9 100644 --- a/src/platform/graphics/webgpu/webgpu-texture.js +++ b/src/platform/graphics/webgpu/webgpu-texture.js @@ -526,9 +526,6 @@ class WebgpuTexture { const stagingBuffer = device.createBufferImpl(BUFFERUSAGE_READ | BUFFERUSAGE_COPY_DST); stagingBuffer.allocate(device, size); - // use existing or create new encoder - const commandEncoder = device.commandEncoder ?? device.wgpu.createCommandEncoder(); - const src = { texture: this.gpuTexture, mipLevel: mipLevel, @@ -548,16 +545,9 @@ class WebgpuTexture { }; // copy the GPU texture to the staging buffer + const commandEncoder = device.getCommandEncoder(); commandEncoder.copyTextureToBuffer(src, dst, copySize); - // if we created new encoder - if (!device.commandEncoder) { - DebugHelper.setLabel(commandEncoder, 'copyTextureToBuffer-Encoder'); - const cb = commandEncoder.finish(); - DebugHelper.setLabel(cb, 'copyTextureToBuffer-CommandBuffer'); - device.addCommandBuffer(cb); - } - // async read data from the staging buffer to a temporary array return device.readBuffer(stagingBuffer, size, null, immediate).then((temp) => {