Skip to content

Commit

Permalink
WebGPURenderer: Add Offscreen Support (#27520)
Browse files Browse the repository at this point in the history
* 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

---------
  • Loading branch information
RenaudRohlinger authored Jan 8, 2024
1 parent f017aa9 commit d4e13e5
Show file tree
Hide file tree
Showing 12 changed files with 71 additions and 32 deletions.
22 changes: 13 additions & 9 deletions examples/jsm/capabilities/WebGPU.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,30 @@
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();

This comment has been minimized.

Copy link
@wcandillon

wcandillon Aug 22, 2024

Contributor

@RenaudRohlinger I'm a huge fan of your work 🙋🏼‍♂️ This changes requires us to support top-level async in React Native which I think is unlikely to happen anytime soon. Here is a demo of WebGPU + RN + Three: https://x.com/wcandillon/status/1825862686300672124. Any chance we could make getStaticAdapter async instead?


}

class WebGPU {

static isAvailable() {

return Boolean( isAvailable );

}

static getStaticAdapter() {

return isAvailable;

}
Expand Down Expand Up @@ -50,4 +53,5 @@ class WebGPU {

}


export default WebGPU;
15 changes: 15 additions & 0 deletions examples/jsm/loaders/KTX2Loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 ) {
Expand Down
2 changes: 2 additions & 0 deletions examples/jsm/renderers/common/Backend.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ class Backend {

// utils

hasFeatureAsync( name ) { } // return Boolean

hasFeature( name ) { } // return Boolean

getInstanceCount( renderObject ) {
Expand Down
6 changes: 6 additions & 0 deletions examples/jsm/renderers/common/Renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -770,6 +770,12 @@ class Renderer {

}

hasFeatureAsync( name ) {

return this.backend.hasFeatureAsync( name );

}

hasFeature( name ) {

return this.backend.hasFeature( name );
Expand Down
6 changes: 6 additions & 0 deletions examples/jsm/renderers/webgl/WebGLBackend.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
Expand Down
31 changes: 18 additions & 13 deletions examples/jsm/renderers/webgpu/WebGPUBackend.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';

//

Expand Down Expand Up @@ -1070,17 +1061,31 @@ class WebGPUBackend extends Backend {
return 16;

}

async hasFeatureAsync( name ) {

hasFeature( name ) {

const adapter = this.adapter || _staticAdapter;
const adapter = this.adapter || await WebGPU.getStaticAdapter();

//

return adapter.features.has( name );

}

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 );
Expand Down
3 changes: 2 additions & 1 deletion examples/jsm/renderers/webgpu/WebGPURenderer.js
Original file line number Diff line number Diff line change
@@ -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 = {
Expand Down
2 changes: 1 addition & 1 deletion examples/jsm/renderers/webgpu/nodes/WGSLNodeBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion examples/webgpu_instance_mesh.html
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@

init();

function init() {
async function init() {

if ( WebGPU.isAvailable() === false && WebGL.isWebGL2Available() === false ) {

Expand Down
4 changes: 2 additions & 2 deletions examples/webgpu_loader_gltf_compressed.html
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
Expand Down
6 changes: 3 additions & 3 deletions examples/webgpu_morphtargets_face.html
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@

init();

function init() {
async function init() {

if ( WebGPU.isAvailable() === false && WebGL.isWebGL2Available() === false ) {

Expand Down Expand Up @@ -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 )
Expand Down
4 changes: 2 additions & 2 deletions examples/webgpu_sandbox.html
Original file line number Diff line number Diff line change
Expand Up @@ -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' );

Expand Down

0 comments on commit d4e13e5

Please sign in to comment.