Browse Source

WebGPURenderer: Prevent duplicated init requests (#25964)

Currently WebGPURenderer init() requests can be duplicated
for example by contiguous .render() calls without await.

With this commit init() request (promise) is cached and
the duplicated requests can be avoided.
Takahiro 2 years ago
parent
commit
ea321889db
1 changed files with 61 additions and 45 deletions
  1. 61 45
      examples/jsm/renderers/webgpu/WebGPURenderer.js

+ 61 - 45
examples/jsm/renderers/webgpu/WebGPURenderer.js

@@ -150,6 +150,7 @@ class WebGPURenderer {
 		this._renderTarget = null;
 
 		this._initialized = false;
+		this._initPromise = null;
 
 		// some parameters require default values other than "undefined"
 
@@ -183,75 +184,90 @@ class WebGPURenderer {
 
 		}
 
-		const parameters = this._parameters;
+		if ( this._initPromise !== null ) {
 
-		const adapterOptions = {
-			powerPreference: parameters.powerPreference
-		};
+			return this._initPromise;
 
-		const adapter = await navigator.gpu.requestAdapter( adapterOptions );
+		}
 
-		if ( adapter === null ) {
+		this._initPromise = new Promise( async ( resolve, reject ) => {
 
-			throw new Error( 'WebGPURenderer: Unable to create WebGPU adapter.' );
+			const parameters = this._parameters;
 
-		}
+			const adapterOptions = {
+				powerPreference: parameters.powerPreference
+			};
 
-		// feature support
+			const adapter = await navigator.gpu.requestAdapter( adapterOptions );
 
-		const features = Object.values( GPUFeatureName );
+			if ( adapter === null ) {
 
-		const supportedFeatures = [];
+				reject( new Error( 'WebGPURenderer: Unable to create WebGPU adapter.' ) );
+				return;
 
-		for ( const name of features ) {
+			}
 
-			if ( adapter.features.has( name ) ) {
+			// feature support
 
-				supportedFeatures.push( name );
+			const features = Object.values( GPUFeatureName );
+
+			const supportedFeatures = [];
+
+			for ( const name of features ) {
+
+				if ( adapter.features.has( name ) ) {
+
+					supportedFeatures.push( name );
+
+				}
 
 			}
 
-		}
+			const deviceDescriptor = {
+				requiredFeatures: supportedFeatures,
+				requiredLimits: parameters.requiredLimits
+			};
 
-		const deviceDescriptor = {
-			requiredFeatures: supportedFeatures,
-			requiredLimits: parameters.requiredLimits
-		};
+			const device = await adapter.requestDevice( deviceDescriptor );
 
-		const device = await adapter.requestDevice( deviceDescriptor );
+			const context = ( parameters.context !== undefined ) ? parameters.context : this.domElement.getContext( 'webgpu' );
 
-		const context = ( parameters.context !== undefined ) ? parameters.context : this.domElement.getContext( 'webgpu' );
+			this._adapter = adapter;
+			this._device = device;
+			this._context = context;
 
-		this._adapter = adapter;
-		this._device = device;
-		this._context = context;
+			this._configureContext();
 
-		this._configureContext();
+			this._info = new WebGPUInfo();
+			this._properties = new WebGPUProperties();
+			this._attributes = new WebGPUAttributes( device );
+			this._geometries = new WebGPUGeometries( this._attributes, this._properties, this._info );
+			this._textures = new WebGPUTextures( device, this._properties, this._info );
+			this._utils = new WebGPUUtils( this );
+			this._nodes = new WebGPUNodes( this, this._properties );
+			this._objects = new WebGPURenderObjects( this, this._nodes, this._geometries, this._info );
+			this._computePipelines = new WebGPUComputePipelines( device, this._nodes );
+			this._renderPipelines = new WebGPURenderPipelines( device, this._nodes, this._utils );
+			this._bindings = this._renderPipelines.bindings = new WebGPUBindings( device, this._info, this._properties, this._textures, this._renderPipelines, this._computePipelines, this._attributes, this._nodes );
+			this._renderLists = new WebGPURenderLists();
+			this._renderStates = new WebGPURenderStates();
+			this._background = new WebGPUBackground( this, this._properties );
 
-		this._info = new WebGPUInfo();
-		this._properties = new WebGPUProperties();
-		this._attributes = new WebGPUAttributes( device );
-		this._geometries = new WebGPUGeometries( this._attributes, this._properties, this._info );
-		this._textures = new WebGPUTextures( device, this._properties, this._info );
-		this._utils = new WebGPUUtils( this );
-		this._nodes = new WebGPUNodes( this, this._properties );
-		this._objects = new WebGPURenderObjects( this, this._nodes, this._geometries, this._info );
-		this._computePipelines = new WebGPUComputePipelines( device, this._nodes );
-		this._renderPipelines = new WebGPURenderPipelines( device, this._nodes, this._utils );
-		this._bindings = this._renderPipelines.bindings = new WebGPUBindings( device, this._info, this._properties, this._textures, this._renderPipelines, this._computePipelines, this._attributes, this._nodes );
-		this._renderLists = new WebGPURenderLists();
-		this._renderStates = new WebGPURenderStates();
-		this._background = new WebGPUBackground( this, this._properties );
+			//
 
-		//
+			this._setupColorBuffer();
+			this._setupDepthBuffer();
 
-		this._setupColorBuffer();
-		this._setupDepthBuffer();
+			this._animation.setNodes( this._nodes );
+			this._animation.start();
+
+			this._initialized = true;
+
+			resolve();
 
-		this._animation.setNodes( this._nodes );
-		this._animation.start();
+		} );
 
-		this._initialized = true;
+		return this._initPromise;
 
 	}