Pārlūkot izejas kodu

WebGPURenderer: Add Offscreen Support (#27520)

* add offscreen support

* refactor statics webgpu

* navigator.gpu should be enough for initial check

* fix webgl context ktx2loader

* use isAvailable in webgpurenderer

* cleanup and should fix pupeeter

* return promise

* feedbacks

* remove unecessary async

* removed oversight

* cleanup

---------
Renaud Rohlinger 1 gadu atpakaļ
vecāks
revīzija
d4e13e525b

+ 13 - 9
examples/jsm/capabilities/WebGPU.js

@@ -1,20 +1,17 @@
-if ( window.GPUShaderStage === undefined ) {
+if ( self.GPUShaderStage === undefined ) {
 
-	window.GPUShaderStage = { VERTEX: 1, FRAGMENT: 2, COMPUTE: 4 };
+	self.GPUShaderStage = { VERTEX: 1, FRAGMENT: 2, COMPUTE: 4 };
 
 }
 
-let isAvailable = false;
+// statics
 
-if ( navigator.gpu !== undefined ) {
+let isAvailable = navigator.gpu !== undefined;
 
-	const adapter = await navigator.gpu.requestAdapter();
 
-	if ( adapter !== null ) {
+if ( typeof window !== 'undefined' && isAvailable ) {
 
-		isAvailable = true;
-
-	}
+	isAvailable = await navigator.gpu.requestAdapter();
 
 }
 
@@ -22,6 +19,12 @@ class WebGPU {
 
 	static isAvailable() {
 
+		return Boolean( isAvailable );
+
+	}
+
+	static getStaticAdapter() {
+
 		return isAvailable;
 
 	}
@@ -50,4 +53,5 @@ class WebGPU {
 
 }
 
+
 export default WebGPU;

+ 15 - 0
examples/jsm/loaders/KTX2Loader.js

@@ -120,6 +120,21 @@ class KTX2Loader extends Loader {
 
 	}
 
+	async detectSupportAsync( renderer ) {
+
+		this.workerConfig = {
+			astcSupported: await renderer.hasFeatureAsync( 'texture-compression-astc' ),
+			etc1Supported: await renderer.hasFeatureAsync( 'texture-compression-etc1' ),
+			etc2Supported: await renderer.hasFeatureAsync( 'texture-compression-etc2' ),
+			dxtSupported: await renderer.hasFeatureAsync( 'texture-compression-bc' ),
+			bptcSupported: await renderer.hasFeatureAsync( 'texture-compression-bptc' ),
+			pvrtcSupported: await renderer.hasFeatureAsync( 'texture-compression-pvrtc' )
+		};
+
+		return this;
+
+	}
+
 	detectSupport( renderer ) {
 
 		if ( renderer.isWebGPURenderer === true ) {

+ 2 - 0
examples/jsm/renderers/common/Backend.js

@@ -90,6 +90,8 @@ class Backend {
 
 	// utils
 
+	hasFeatureAsync( name ) { } // return Boolean
+
 	hasFeature( name ) { } // return Boolean
 
 	getInstanceCount( renderObject ) {

+ 6 - 0
examples/jsm/renderers/common/Renderer.js

@@ -770,6 +770,12 @@ class Renderer {
 
 	}
 
+	hasFeatureAsync( name ) {
+
+		return this.backend.hasFeatureAsync( name );
+
+	}
+
 	hasFeature( name ) {
 
 		return this.backend.hasFeature( name );

+ 6 - 0
examples/jsm/renderers/webgl/WebGLBackend.js

@@ -837,6 +837,12 @@ class WebGLBackend extends Backend {
 
 	}
 
+	async hasFeatureAsync( name ) {
+
+		return this.hasFeature( name );
+
+	}
+
 	hasFeature( name ) {
 
 		const keysMatching = Object.keys( GLFeatureName ).filter( key => GLFeatureName[ key ] === name );

+ 18 - 13
examples/jsm/renderers/webgpu/WebGPUBackend.js

@@ -14,16 +14,7 @@ import WebGPUAttributeUtils from './utils/WebGPUAttributeUtils.js';
 import WebGPUBindingUtils from './utils/WebGPUBindingUtils.js';
 import WebGPUPipelineUtils from './utils/WebGPUPipelineUtils.js';
 import WebGPUTextureUtils from './utils/WebGPUTextureUtils.js';
-
-// statics
-
-let _staticAdapter = null;
-
-if ( navigator.gpu !== undefined ) {
-
-	_staticAdapter = await navigator.gpu.requestAdapter();
-
-}
+import WebGPU from '../../capabilities/WebGPU.js';
 
 //
 
@@ -1070,10 +1061,10 @@ class WebGPUBackend extends Backend {
 		return 16;
 
 	}
+		
+	async hasFeatureAsync( name ) {
 
-	hasFeature( name ) {
-
-		const adapter = this.adapter || _staticAdapter;
+		const adapter = this.adapter || await WebGPU.getStaticAdapter();
 
 		//
 
@@ -1081,6 +1072,20 @@ class WebGPUBackend extends Backend {
 
 	}
 
+	hasFeature( name ) {
+
+		if ( !this.adapter ) {
+
+			console.warn( 'WebGPUBackend: WebGPU adapter has not been initialized yet. Please use detectSupportAsync instead' );
+
+			return false;
+
+		}
+
+		return this.adapter.features.has( name );
+
+	}
+
 	copyFramebufferToTexture( texture, renderContext ) {
 
 		const renderContextData = this.get( renderContext );

+ 2 - 1
examples/jsm/renderers/webgpu/WebGPURenderer.js

@@ -1,7 +1,8 @@
+import WebGPU from '../../capabilities/WebGPU.js';
+
 import Renderer from '../common/Renderer.js';
 import WebGLBackend from '../webgl/WebGLBackend.js';
 import WebGPUBackend from './WebGPUBackend.js';
-import WebGPU from '../../capabilities/WebGPU.js';
 /*
 const debugHandler = {
 

+ 1 - 1
examples/jsm/renderers/webgpu/nodes/WGSLNodeBuilder.js

@@ -16,7 +16,7 @@ import { getFormat } from '../utils/WebGPUTextureUtils.js';
 import WGSLNodeParser from './WGSLNodeParser.js';
 
 // GPUShaderStage is not defined in browsers not supporting WebGPU
-const GPUShaderStage = window.GPUShaderStage;
+const GPUShaderStage = self.GPUShaderStage;
 
 const gpuShaderStageLib = {
 	'vertex': GPUShaderStage ? GPUShaderStage.VERTEX : 1,

+ 1 - 1
examples/webgpu_instance_mesh.html

@@ -44,7 +44,7 @@
 
 			init();
 
-			function init() {
+			async function init() {
 
 				if ( WebGPU.isAvailable() === false && WebGL.isWebGL2Available() === false ) {
 

+ 2 - 2
examples/webgpu_loader_gltf_compressed.html

@@ -67,9 +67,9 @@
 				controls.maxDistance = 6;
 				controls.update();
 
-				const ktx2Loader = new KTX2Loader()
+				const ktx2Loader = await new KTX2Loader()
 					.setTranscoderPath( 'jsm/libs/basis/' )
-					.detectSupport( renderer );
+					.detectSupportAsync( renderer );
 
 				const loader = new GLTFLoader();
 				loader.setKTX2Loader( ktx2Loader );

+ 3 - 3
examples/webgpu_morphtargets_face.html

@@ -48,7 +48,7 @@
 
 			init();
 
-			function init() {
+			async function init() {
 
 				if ( WebGPU.isAvailable() === false && WebGL.isWebGL2Available() === false ) {
 
@@ -79,9 +79,9 @@
 
 				container.appendChild( renderer.domElement );
 
-				const ktx2Loader = new KTX2Loader()
+				const ktx2Loader = await new KTX2Loader()
 					.setTranscoderPath( 'jsm/libs/basis/' )
-					.detectSupport( renderer );
+					.detectSupportAsync( renderer );
 
 				new GLTFLoader()
 					.setKTX2Loader( ktx2Loader )

+ 2 - 2
examples/webgpu_sandbox.html

@@ -74,9 +74,9 @@
 				textureDisplace.wrapS = THREE.RepeatWrapping;
 				textureDisplace.wrapT = THREE.RepeatWrapping;
 
-				const ktxLoader = new KTX2Loader()
+				const ktxLoader = await new KTX2Loader()
 					.setTranscoderPath( 'jsm/libs/basis/' )
-					.detectSupport( renderer );
+					.detectSupportAsync( renderer );
 
 				const ktxTexture = await ktxLoader.loadAsync( './textures/compressed/sample_uastc_zstd.ktx2' );