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

WebXRManager: Lazily initialise XRWebGLBinding (#31648)

* lazily initialise XRWebGLBinding

* add comment with PR ref for _supportsLayers

* `WebXRManager.getBinding()` creates `XRWebGLBinding` if needed + use elsewhere in `WebXRManager`

* XRManager: add getBinding for lazy init of glBinding
harryhjsh 5 месяцев назад
Родитель
Сommit
5a16f4bf3d
2 измененных файлов с 66 добавлено и 42 удалено
  1. 35 19
      src/renderers/common/XRManager.js
  2. 31 23
      src/renderers/webxr/WebXRManager.js

+ 35 - 19
src/renderers/common/XRManager.js

@@ -164,12 +164,12 @@ class XRManager extends EventDispatcher {
 		this._layers = [];
 
 		/**
-		 * Whether the device has support for all layer types.
+		 * Whether the XR session uses layers.
 		 *
 		 * @type {boolean}
 		 * @default false
 		 */
-		this._supportsLayers = false;
+		this._sessionUsesLayers = false;
 
 		/**
 		 * Whether the device supports binding gl objects.
@@ -360,13 +360,16 @@ class XRManager extends EventDispatcher {
 		this._xrFrame = null;
 
 		/**
-		 * Whether to use the WebXR Layers API or not.
+		 * Whether the browser supports the APIs necessary to use XRProjectionLayers.
+		 *
+		 * Note: this does not represent XRSession explicitly requesting
+		 * `'layers'` as a feature - see `_sessionUsesLayers` and #30112
 		 *
 		 * @private
 		 * @type {boolean}
 		 * @readonly
 		 */
-		this._useLayers = ( this._supportsGlBinding && 'createProjectionLayer' in XRWebGLBinding.prototype ); // eslint-disable-line compat/compat
+		this._supportsLayers = ( this._supportsGlBinding && 'createProjectionLayer' in XRWebGLBinding.prototype ); // eslint-disable-line compat/compat
 
 		/**
 		 * Whether the usage of multiview has been requested by the application or not.
@@ -587,6 +590,27 @@ class XRManager extends EventDispatcher {
 
 	}
 
+
+	/**
+	 * Return the current XR binding.
+	 *
+	 * Creates a new binding if needed and the browser is
+	 * capable of doing so.
+	 *
+	 * @return {?XRWebGLBinding} The XR binding. Returns `null` if a binding cannot be crated.
+	 */
+	getBinding() {
+
+		if ( this._glBinding === null && this._supportsGlBinding ) {
+
+			this._glBinding = new XRWebGLBinding( this._session, this._gl );
+
+		}
+
+		return this._glBinding;
+
+	}
+
 	/**
 	 * Returns the current XR frame.
 	 *
@@ -817,7 +841,7 @@ class XRManager extends EventDispatcher {
 			layer.renderTarget.isXRRenderTarget = this._session !== null;
 			layer.renderTarget._hasExternalTextures = layer.renderTarget.isXRRenderTarget;
 
-			if ( layer.renderTarget.isXRRenderTarget && this._supportsLayers ) {
+			if ( layer.renderTarget.isXRRenderTarget && this._sessionUsesLayers ) {
 
 				layer.xrlayer.transform = new XRRigidTransform( layer.plane.getWorldPosition( translationObject ), layer.plane.getWorldQuaternion( quaternionObject ) );
 
@@ -924,16 +948,7 @@ class XRManager extends EventDispatcher {
 
 			//
 
-			if ( this._supportsGlBinding ) {
-
-				const glBinding = new XRWebGLBinding( session, gl );
-				this._glBinding = glBinding;
-
-			}
-
-			//
-
-			if ( this._useLayers === true ) {
+			if ( this._supportsLayers === true ) {
 
 				// default path using XRProjectionLayer
 
@@ -963,6 +978,7 @@ class XRManager extends EventDispatcher {
 
 				}
 
+				this._glBinding = this.getBinding();
 				const glProjLayer = this._glBinding.createProjectionLayer( projectionlayerInit );
 				const layersArray = [ glProjLayer ];
 
@@ -993,11 +1009,11 @@ class XRManager extends EventDispatcher {
 				this._xrRenderTarget._hasExternalTextures = true;
 				this._xrRenderTarget.depth = this._useMultiview ? 2 : 1;
 
-				this._supportsLayers = session.enabledFeatures.includes( 'layers' );
+				this._sessionUsesLayers = session.enabledFeatures.includes( 'layers' );
 
 				this._referenceSpace = await session.requestReferenceSpace( this.getReferenceSpaceType() );
 
-				if ( this._supportsLayers ) {
+				if ( this._sessionUsesLayers ) {
 
 					// switch layers to native
 					for ( const layer of this._layers ) {
@@ -1366,7 +1382,7 @@ function onSessionEnd() {
 	this._xrRenderTarget = null;
 
 	// switch layers back to emulated
-	if ( this._supportsLayers === true ) {
+	if ( this._sessionUsesLayers === true ) {
 
 		for ( const layer of this._layers ) {
 
@@ -1568,7 +1584,7 @@ function onAnimationFrame( time, frame ) {
 
 			let viewport;
 
-			if ( this._useLayers === true ) {
+			if ( this._supportsLayers === true ) {
 
 				const glSubImage = this._glBinding.getViewSubImage( this._glProjLayer, view );
 				viewport = glSubImage.viewport;

+ 31 - 23
src/renderers/webxr/WebXRManager.js

@@ -52,6 +52,8 @@ class WebXRManager extends EventDispatcher {
 		let glBaseLayer = null;
 		let xrFrame = null;
 
+		const supportsGlBinding = typeof XRWebGLBinding !== 'undefined';
+
 		const depthSensing = new WebXRDepthSensing();
 		const cameraAccessTextures = {};
 		const attributes = gl.getContextAttributes();
@@ -340,10 +342,19 @@ class WebXRManager extends EventDispatcher {
 		/**
 		 * Returns the current XR binding.
 		 *
-		 * @return {?XRWebGLBinding} The XR binding.
+		 * Creates a new binding if needed and the browser is
+		 * capable of doing so.
+		 *
+		 * @return {?XRWebGLBinding} The XR binding. Returns `null` if one cannot be created.
 		 */
 		this.getBinding = function () {
 
+			if ( glBinding === null && supportsGlBinding ) {
+
+				glBinding = new XRWebGLBinding( session, gl );
+
+			}
+
 			return glBinding;
 
 		};
@@ -405,17 +416,12 @@ class WebXRManager extends EventDispatcher {
 				currentPixelRatio = renderer.getPixelRatio();
 				renderer.getSize( currentSize );
 
-				if ( typeof XRWebGLBinding !== 'undefined' ) {
-
-					glBinding = new XRWebGLBinding( session, gl );
-
-				}
 
 				// Check that the browser implements the necessary APIs to use an
 				// XRProjectionLayer rather than an XRWebGLLayer
-				const useLayers = glBinding !== null && 'createProjectionLayer' in XRWebGLBinding.prototype;
+				const supportsLayers = supportsGlBinding && 'createProjectionLayer' in XRWebGLBinding.prototype;
 
-				if ( ! useLayers ) {
+				if ( ! supportsLayers ) {
 
 					const layerInit = {
 						antialias: attributes.antialias,
@@ -466,6 +472,8 @@ class WebXRManager extends EventDispatcher {
 						scaleFactor: framebufferScaleFactor
 					};
 
+					glBinding = this.getBinding();
+
 					glProjLayer = glBinding.createProjectionLayer( projectionlayerInit );
 
 					session.updateRenderState( { layers: [ glProjLayer ] } );
@@ -992,7 +1000,9 @@ class WebXRManager extends EventDispatcher {
 					enabledFeatures.includes( 'depth-sensing' ) &&
 					session.depthUsage == 'gpu-optimized';
 
-				if ( gpuDepthSensingEnabled && glBinding ) {
+				if ( gpuDepthSensingEnabled && supportsGlBinding ) {
+
+					glBinding = scope.getBinding();
 
 					const depthData = glBinding.getDepthInformation( views[ 0 ] );
 
@@ -1007,32 +1017,30 @@ class WebXRManager extends EventDispatcher {
 				const cameraAccessEnabled = enabledFeatures &&
 				    enabledFeatures.includes( 'camera-access' );
 
-				if ( cameraAccessEnabled ) {
+				if ( cameraAccessEnabled && supportsGlBinding ) {
 
 					renderer.state.unbindTexture();
 
-					if ( glBinding ) {
+					glBinding = scope.getBinding();
 
-						for ( let i = 0; i < views.length; i ++ ) {
+					for ( let i = 0; i < views.length; i ++ ) {
 
-							const camera = views[ i ].camera;
+						const camera = views[ i ].camera;
 
-							if ( camera ) {
+						if ( camera ) {
 
-								let cameraTex = cameraAccessTextures[ camera ];
+							let cameraTex = cameraAccessTextures[ camera ];
 
-								if ( ! cameraTex ) {
+							if ( ! cameraTex ) {
 
-									cameraTex = new ExternalTexture();
-									cameraAccessTextures[ camera ] = cameraTex;
-
-								}
-
-								const glTexture = glBinding.getCameraImage( camera );
-								cameraTex.sourceTexture = glTexture;
+								cameraTex = new ExternalTexture();
+								cameraAccessTextures[ camera ] = cameraTex;
 
 							}
 
+							const glTexture = glBinding.getCameraImage( camera );
+							cameraTex.sourceTexture = glTexture;
+
 						}
 
 					}

粤ICP备19079148号