Просмотр исходного кода

WebGPURenderer: Handle Device Lost Event (#29767)

* WebGPURenderer: Handle Device Lost Event

* small typo

* feedbacks

* fix

* not need to bind
Renaud Rohlinger 1 год назад
Родитель
Сommit
ab048e655e

+ 2 - 0
src/renderers/common/Backend.js

@@ -193,6 +193,8 @@ class Backend {
 
 	}
 
+	dispose() { }
+
 }
 
 export default Backend;

+ 27 - 0
src/renderers/common/Renderer.js

@@ -143,6 +143,9 @@ class Renderer {
 
 		this._handleObjectFunction = this._renderObjectDirect;
 
+		this._isDeviceLost = false;
+		this.onDeviceLost = this._onDeviceLost;
+
 		this._initialized = false;
 		this._initPromise = null;
 
@@ -265,6 +268,8 @@ class Renderer {
 
 	async compileAsync( scene, camera, targetScene = null ) {
 
+		if ( this._isDeviceLost === true ) return;
+
 		if ( this._initialized === false ) await this.init();
 
 		// preserve render tree
@@ -418,6 +423,23 @@ class Renderer {
 
 	}
 
+	_onDeviceLost( info ) {
+
+		let errorMessage = `THREE.WebGPURenderer: ${info.api} Device Lost:\n\nMessage: ${info.message}`;
+
+		if ( info.reason ) {
+
+			errorMessage += `\nReason: ${info.reason}`;
+
+		}
+
+		console.error( errorMessage );
+
+		this._isDeviceLost = true;
+
+	}
+
+
 	_renderBundle( bundle, sceneRef, lightsNode ) {
 
 		const { bundleGroup, camera, renderList } = bundle;
@@ -552,6 +574,8 @@ class Renderer {
 
 	_renderScene( scene, camera, useFrameBufferTarget = true ) {
 
+		if ( this._isDeviceLost === true ) return;
+
 		const frameBufferTarget = useFrameBufferTarget ? this._getFrameBufferTarget() : null;
 
 		// preserve render tree
@@ -1120,6 +1144,7 @@ class Renderer {
 	dispose() {
 
 		this.info.dispose();
+		this.backend.dispose();
 
 		this._animation.dispose();
 		this._objects.dispose();
@@ -1163,6 +1188,8 @@ class Renderer {
 
 	compute( computeNodes ) {
 
+		if ( this.isDeviceLost === true ) return;
+
 		if ( this._initialized === false ) {
 
 			console.warn( 'THREE.Renderer: .compute() called before the backend is initialized. Try using .computeAsync() instead.' );

+ 25 - 0
src/renderers/webgl-fallback/WebGLBackend.js

@@ -36,6 +36,25 @@ class WebGLBackend extends Backend {
 
 		const glContext = ( parameters.context !== undefined ) ? parameters.context : renderer.domElement.getContext( 'webgl2' );
 
+	 	function onContextLost( event ) {
+
+			event.preventDefault();
+
+			const contextLossInfo = {
+				api: 'WebGL',
+				message: event.statusMessage || 'Unknown reason',
+				reason: null,
+				originalEvent: event
+			};
+
+			renderer.onDeviceLost( contextLossInfo );
+
+		}
+
+		this._onContextLost = onContextLost;
+
+		renderer.domElement.addEventListener( 'webglcontextlost', onContextLost, false );
+
 		this.gl = glContext;
 
 		this.extensions = new WebGLExtensions( this );
@@ -1656,6 +1675,12 @@ class WebGLBackend extends Backend {
 
 	}
 
+	dispose() {
+
+		this.renderer.domElement.removeEventListener( 'webglcontextlost', this._onContextLost );
+
+	}
+
 }
 
 export default WebGLBackend;

+ 13 - 0
src/renderers/webgpu/WebGPUBackend.js

@@ -101,6 +101,19 @@ class WebGPUBackend extends Backend {
 
 		}
 
+		device.lost.then( ( info ) => {
+
+			const deviceLossInfo = {
+				api: 'WebGPU',
+				message: info.message || 'Unknown reason',
+				reason: info.reason || null,
+				originalEvent: info
+			};
+
+			renderer.onDeviceLost( deviceLossInfo );
+
+		} );
+
 		const context = ( parameters.context !== undefined ) ? parameters.context : renderer.domElement.getContext( 'webgpu' );
 
 		this.device = device;

粤ICP备19079148号