Răsfoiți Sursa

WebGPURenderer: Use renderBundles for repeated mipmap creation. (#29197)

* mip bundle

* Update WebGPUTexturePassUtils.js

Clean up.

* label pipelines

* simplify

---------

Co-authored-by: aardgoose <angus.sawyer@email.com>
Co-authored-by: Michael Herzog <michael.herzog@human-interactive.org>
aardgoose 1 an în urmă
părinte
comite
09430e8fc5
1 a modificat fișierele cu 62 adăugiri și 5 ștergeri
  1. 62 5
      src/renderers/webgpu/utils/WebGPUTexturePassUtils.js

+ 62 - 5
src/renderers/webgpu/utils/WebGPUTexturePassUtils.js

@@ -1,9 +1,12 @@
+import DataMap from '../../common/DataMap.js';
 import { GPUTextureViewDimension, GPUIndexFormat, GPUFilterMode, GPUPrimitiveTopology, GPULoadOp, GPUStoreOp } from './WebGPUConstants.js';
 
-class WebGPUTexturePassUtils {
+class WebGPUTexturePassUtils extends DataMap {
 
 	constructor( device ) {
 
+		super();
+
 		this.device = device;
 
 		const mipmapVertexSource = `
@@ -99,6 +102,7 @@ fn main( @location( 0 ) vTex : vec2<f32> ) -> @location( 0 ) vec4<f32> {
 		if ( pipeline === undefined ) {
 
 			pipeline = this.device.createRenderPipeline( {
+				label: `mipmap-${ format }`,
 				vertex: {
 					module: this.mipmapVertexShaderModule,
 					entryPoint: 'main'
@@ -130,6 +134,7 @@ fn main( @location( 0 ) vTex : vec2<f32> ) -> @location( 0 ) vec4<f32> {
 		if ( pipeline === undefined ) {
 
 			pipeline = this.device.createRenderPipeline( {
+				label: `flipY-${ format }`,
 				vertex: {
 					module: this.mipmapVertexShaderModule,
 					entryPoint: 'main'
@@ -226,9 +231,33 @@ fn main( @location( 0 ) vTex : vec2<f32> ) -> @location( 0 ) vec4<f32> {
 
 	generateMipmaps( textureGPU, textureGPUDescriptor, baseArrayLayer = 0 ) {
 
-		const pipeline = this.getTransferPipeline( textureGPUDescriptor.format );
+		const textureData = this.get( textureGPU );
+
+		if ( textureData.useCount === undefined ) {
+
+			textureData.useCount = 0;
+			textureData.layers = [];
+
+		}
+
+		const passes = textureData.layers[ baseArrayLayer ] || this._mipmapCreateBundles( textureGPU, textureGPUDescriptor, baseArrayLayer );
 
 		const commandEncoder = this.device.createCommandEncoder( {} );
+
+		this._mipmapRunBundles( commandEncoder, passes );
+
+		this.device.queue.submit( [ commandEncoder.finish() ] );
+
+		if ( textureData.useCount !== 0 ) textureData.layers[ baseArrayLayer ] = passes;
+
+		textureData.useCount ++;
+
+	}
+
+	_mipmapCreateBundles( textureGPU, textureGPUDescriptor, baseArrayLayer ) {
+
+		const pipeline = this.getTransferPipeline( textureGPUDescriptor.format );
+
 		const bindGroupLayout = pipeline.getBindGroupLayout( 0 ); // @TODO: Consider making this static.
 
 		let srcView = textureGPU.createView( {
@@ -238,6 +267,8 @@ fn main( @location( 0 ) vTex : vec2<f32> ) -> @location( 0 ) vec4<f32> {
 			baseArrayLayer
 		} );
 
+		const passes = [];
+
 		for ( let i = 1; i < textureGPUDescriptor.mipLevelCount; i ++ ) {
 
 			const bindGroup = this.device.createBindGroup( {
@@ -258,25 +289,51 @@ fn main( @location( 0 ) vTex : vec2<f32> ) -> @location( 0 ) vec4<f32> {
 				baseArrayLayer
 			} );
 
-			const passEncoder = commandEncoder.beginRenderPass( {
+			const passDescriptor = {
 				colorAttachments: [ {
 					view: dstView,
 					loadOp: GPULoadOp.Clear,
 					storeOp: GPUStoreOp.Store,
 					clearValue: [ 0, 0, 0, 0 ]
 				} ]
+			};
+
+			const passEncoder = this.device.createRenderBundleEncoder( {
+				colorFormats: [ textureGPUDescriptor.format ]
 			} );
 
 			passEncoder.setPipeline( pipeline );
 			passEncoder.setBindGroup( 0, bindGroup );
 			passEncoder.draw( 4, 1, 0, 0 );
-			passEncoder.end();
+
+			passes.push( {
+				renderBundles: [ passEncoder.finish() ],
+				passDescriptor
+			} );
 
 			srcView = dstView;
 
 		}
 
-		this.device.queue.submit( [ commandEncoder.finish() ] );
+		return passes;
+
+	}
+
+	_mipmapRunBundles( commandEncoder, passes ) {
+
+		const levels = passes.length;
+
+		for ( let i = 0; i < levels; i ++ ) {
+
+			const pass = passes[ i ];
+
+			const passEncoder = commandEncoder.beginRenderPass( pass.passDescriptor );
+
+			passEncoder.executeBundles( pass.renderBundles );
+
+			passEncoder.end();
+
+		}
 
 	}
 

粤ICP备19079148号