ソースを参照

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 年 前
コミット
ea321889db
1 ファイル変更61 行追加45 行削除
  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;
 
 	}