From 92d04568df5a79a0e789dbca80e4c6ca190b7639 Mon Sep 17 00:00:00 2001 From: Renaud Rohlinger Date: Tue, 26 Nov 2024 15:38:00 +0900 Subject: [PATCH 1/2] WebGPUBackend: Simplify Timestamp Queries and Ensure Work Done --- src/renderers/webgpu/WebGPUBackend.js | 63 ++++++++++----------------- 1 file changed, 24 insertions(+), 39 deletions(-) diff --git a/src/renderers/webgpu/WebGPUBackend.js b/src/renderers/webgpu/WebGPUBackend.js index 0fde9a319689e8..f4666cd24ec486 100644 --- a/src/renderers/webgpu/WebGPUBackend.js +++ b/src/renderers/webgpu/WebGPUBackend.js @@ -1166,7 +1166,7 @@ class WebGPUBackend extends Backend { } - async initTimestampQuery( renderContext, descriptor ) { + initTimestampQuery( renderContext, descriptor ) { if ( ! this.trackTimestamp ) return; @@ -1175,27 +1175,8 @@ class WebGPUBackend extends Backend { if ( ! renderContextData.timeStampQuerySet ) { - // Push an error scope to catch any errors during query set creation - this.device.pushErrorScope( 'out-of-memory' ); - - const timeStampQuerySet = await this.device.createQuerySet( { type: 'timestamp', count: 2, label: `timestamp_renderContext_${renderContext.id}` } ); - - // Pop the error scope and check for errors - const error = await this.device.popErrorScope(); - - if ( error ) { - - if ( ! renderContextData.attemptingTimeStampQuerySetFailed ) { - - console.error( `[GPUOutOfMemoryError][renderContext_${renderContext.id}]:\nFailed to create timestamp query set. This may be because timestamp queries are already running in other tabs.` ); - renderContextData.attemptingTimeStampQuerySetFailed = true; - - } - - renderContextData.timeStampQuerySet = null; // Mark as unavailable - return; - - } + const type = renderContext.isComputeNode ? 'compute' : 'render'; + const timeStampQuerySet = this.device.createQuerySet( { type: 'timestamp', count: 2, label: `timestamp_${type}_${renderContext.id}` } ); const timestampWrites = { querySet: timeStampQuerySet, @@ -1219,7 +1200,6 @@ class WebGPUBackend extends Backend { const renderContextData = this.get( renderContext ); - if ( ! renderContextData.timeStampQuerySet ) return; const size = 2 * BigInt64Array.BYTES_PER_ELEMENT; @@ -1235,18 +1215,21 @@ class WebGPUBackend extends Backend { label: 'timestamp result buffer', size: size, usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ, - } ), - isMappingPending: false, + } ) }; } - const { resolveBuffer, resultBuffer, isMappingPending } = renderContextData.currentTimestampQueryBuffers; + const { resolveBuffer, resultBuffer } = renderContextData.currentTimestampQueryBuffers; - if ( isMappingPending === true ) return; encoder.resolveQuerySet( renderContextData.timeStampQuerySet, 0, 2, resolveBuffer, 0 ); - encoder.copyBufferToBuffer( resolveBuffer, 0, resultBuffer, 0, size ); + + if ( resultBuffer.mapState === 'unmapped' ) { + + encoder.copyBufferToBuffer( resolveBuffer, 0, resultBuffer, 0, size ); + + } } @@ -1256,29 +1239,31 @@ class WebGPUBackend extends Backend { const renderContextData = this.get( renderContext ); - if ( ! renderContextData.timeStampQuerySet ) return; if ( renderContextData.currentTimestampQueryBuffers === undefined ) return; - const { resultBuffer, isMappingPending } = renderContextData.currentTimestampQueryBuffers; + const { resultBuffer } = renderContextData.currentTimestampQueryBuffers; + - if ( isMappingPending === true ) return; - renderContextData.currentTimestampQueryBuffers.isMappingPending = true; + await this.device.queue.onSubmittedWorkDone(); - resultBuffer.mapAsync( GPUMapMode.READ ).then( () => { + if ( resultBuffer.mapState === 'unmapped' ) { - const times = new BigUint64Array( resultBuffer.getMappedRange() ); - const duration = Number( times[ 1 ] - times[ 0 ] ) / 1000000; + resultBuffer.mapAsync( GPUMapMode.READ ).then( () => { + const times = new BigUint64Array( resultBuffer.getMappedRange() ); + const duration = Number( times[ 1 ] - times[ 0 ] ) / 1000000; - this.renderer.info.updateTimestamp( type, duration ); - resultBuffer.unmap(); + this.renderer.info.updateTimestamp( type, duration ); - renderContextData.currentTimestampQueryBuffers.isMappingPending = false; + resultBuffer.unmap(); - } ); + + } ); + + } } From 20b9153e3af5fad167a5268b2bcc892b3375577c Mon Sep 17 00:00:00 2001 From: Renaud Rohlinger Date: Tue, 26 Nov 2024 15:41:14 +0900 Subject: [PATCH 2/2] cleanup --- src/renderers/webgpu/WebGPUBackend.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/renderers/webgpu/WebGPUBackend.js b/src/renderers/webgpu/WebGPUBackend.js index f4666cd24ec486..17cb0d8711b459 100644 --- a/src/renderers/webgpu/WebGPUBackend.js +++ b/src/renderers/webgpu/WebGPUBackend.js @@ -1239,13 +1239,10 @@ class WebGPUBackend extends Backend { const renderContextData = this.get( renderContext ); - if ( renderContextData.currentTimestampQueryBuffers === undefined ) return; const { resultBuffer } = renderContextData.currentTimestampQueryBuffers; - - await this.device.queue.onSubmittedWorkDone(); if ( resultBuffer.mapState === 'unmapped' ) {