瀏覽代碼

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;
 
 	}