Explorar o código

WebGPURenderer: Improve performances for trackTimestamp in WebGPU (#28741)

* WebGPURenderer: Improve performances for trackTimestamp in WebGPU

* cleanup
Renaud Rohlinger hai 1 ano
pai
achega
41c1832c61
Modificáronse 1 ficheiros con 44 adicións e 29 borrados
  1. 44 29
      examples/jsm/renderers/webgpu/WebGPUBackend.js

+ 44 - 29
examples/jsm/renderers/webgpu/WebGPUBackend.js

@@ -1120,44 +1120,59 @@ class WebGPUBackend extends Backend {
 		const renderContextData = this.get( renderContext );
 		const renderContextData = this.get( renderContext );
 
 
 		const size = 2 * BigInt64Array.BYTES_PER_ELEMENT;
 		const size = 2 * BigInt64Array.BYTES_PER_ELEMENT;
-		const resolveBuffer = this.device.createBuffer( {
-			size,
-			usage: GPUBufferUsage.QUERY_RESOLVE | GPUBufferUsage.COPY_SRC,
-		} );
 
 
-		const resultBuffer = this.device.createBuffer( {
-			size,
-			usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ,
-		} );
+		if ( renderContextData.currentTimestampQueryBuffers === undefined ) {
+
+			renderContextData.currentTimestampQueryBuffers = {
+				resolveBuffer: this.device.createBuffer({
+					label: 'timestamp resolve buffer',
+					size: size,
+					usage: GPUBufferUsage.QUERY_RESOLVE | GPUBufferUsage.COPY_SRC,
+				}),
+				resultBuffer: this.device.createBuffer({
+					label: 'timestamp result buffer',
+					size: size,
+					usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ,
+				}),
+				isMappingPending: false,
+			}
+
+		}
+
+		const { resolveBuffer, resultBuffer, isMappingPending } = renderContextData.currentTimestampQueryBuffers
+
+
+        if ( isMappingPending === true ) return;
 
 
 		encoder.resolveQuerySet( renderContextData.timeStampQuerySet, 0, 2, resolveBuffer, 0 );
 		encoder.resolveQuerySet( renderContextData.timeStampQuerySet, 0, 2, resolveBuffer, 0 );
 		encoder.copyBufferToBuffer( resolveBuffer, 0, resultBuffer, 0, size );
 		encoder.copyBufferToBuffer( resolveBuffer, 0, resultBuffer, 0, size );
 
 
-		renderContextData.currentTimestampQueryBuffer = resultBuffer;
-
 	}
 	}
 
 
-	async resolveTimestampAsync(renderContext, type = 'render') {
-		if (!this.hasFeature(GPUFeatureName.TimestampQuery) || !this.trackTimestamp) return;
+	async resolveTimestampAsync( renderContext, type = 'render' ) {
+
+		if ( ! this.hasFeature( GPUFeatureName.TimestampQuery ) || ! this.trackTimestamp ) return;
 	
 	
 		const renderContextData = this.get(renderContext);
 		const renderContextData = this.get(renderContext);
-		const { currentTimestampQueryBuffer } = renderContextData;
-	
-		if (currentTimestampQueryBuffer === undefined) return;
-
-		const buffer = currentTimestampQueryBuffer;
-
-		try {
-			await buffer.mapAsync(GPUMapMode.READ);
-			const times = new BigUint64Array(buffer.getMappedRange());
-			const duration = Number(times[1] - times[0]) / 1000000;
-			this.renderer.info.updateTimestamp(type, duration);
-		} catch (error) {
-			console.error(`Error mapping buffer: ${error}`);
-			// Optionally handle the error, e.g., re-queue the buffer or skip it
-		} finally {
-			buffer.unmap(); 
-		}
+
+		if ( renderContextData.currentTimestampQueryBuffers === undefined ) return;
+
+		const { resultBuffer, isMappingPending } = renderContextData.currentTimestampQueryBuffers;
+
+        if ( isMappingPending === true ) return;
+
+        renderContextData.currentTimestampQueryBuffers.isMappingPending = true;
+
+		await resultBuffer.mapAsync( GPUMapMode.READ );
+
+		const times = new BigUint64Array( resultBuffer.getMappedRange() );
+		const duration = Number( times[ 1 ] - times[ 0 ] ) / 1000000;
+
+		this.renderer.info.updateTimestamp( type, duration );
+		resultBuffer.unmap();
+
+		renderContextData.currentTimestampQueryBuffers.isMappingPending = false;
+
 	}
 	}