WebGPU supports detecting that it cannot run on non-local devices?

I’m working on a project and I want to utilize WebGPU on the newly released 113 version of Google Chrome. However, I need to ensure that this project can still run WebGL on devices or browsers that don’t support WebGPU.

Therefore, I have set up an if statement to check for WebGPU support. Here is the code, including my imports:

import WebGPURenderer from 'three/examples/jsm/renderers/webgpu/WebGPURenderer.js'

console.log(navigator.gpu);
var renderer;
if (navigator.gpu) {  
    renderer = new WebGPURenderer({ canvas: canvas,antialias: true } );
} else if (window.WebGLRenderingContext) {
  renderer = new THREE.WebGLRenderer({ canvas: canvas,antialias: true} );
}else {
    throw new Error("Your browser does not support WebGL or WebGPU");
  }

It runs quite well on the local environment, and here are my results. However, there seems to be a discrepancy in the color space for fog.fogColor and renderer.setClearColor between WebGPURenderer and WebGLRenderer , as shown in the image. But this is not a major issue.

When I tried to test the project on my other devices, including Windows and mobile devices (where Chrome on Windows supports WebGPU, but WebGPU is not supported on mobile devices), using Chrome v113 browser on the same local network, I encountered an error and the canvas couldn’t be rendered. The error message was: “Uncaught ReferenceError: GPUShaderStage is not defined” at line 18 in WebGPUNodeBuilder.js.

I tried to use dynamic imports to load the WebGPURenderer module only when WebGPU is supported. It turns out that the WebGPU Renderer cannot be loaded correctly. Here’s the code

var renderer;
if (typeof navigator.gpu !== 'undefined' && navigator.gpu.requestAdapter) {
  import('three/examples/jsm/renderers/webgpu/WebGPURenderer.js')
    .then(({ default: WebGPURenderer }) => {
      renderer = new WebGPURenderer({ canvas: canvas, antialias: true });
      // Initialize your scene with the WebGPURenderer here
    })
    .catch((error) => {
      console.error('Failed to load WebGPURenderer:', error);
      // Fallback to WebGLRenderer if you wish or show an error message
      
    });
} else if (window.WebGLRenderingContext) {
  renderer = new THREE.WebGLRenderer({ canvas: canvas, antialias: true });
  // Initialize your scene with the WebGLRenderer here
} else {
  throw new Error("Your browser does not support WebGL or WebGPU");
}

the error is script.js:322 Uncaught TypeError: Cannot set properties of undefined (setting ‘outputColorSpace’)

I’m not sure if there is an error in my code or if something is missing, or if the mechanism of switching renderers is currently not feasible. Please provide guidance on this matter.Thanks!

Based on this error, it sounds like your script might be trying to use the renderer variable before the promise has resolved. Because the promise is not saved anywhere, that’s likely a mistake. Try doing something like:

let renderer;

const rendererPromise = new Promise((resolve, reject) => {
  if ( ... ) {
    resolve(
      import(' ... ').then(({default: WebGPURenderer}) => {
        return new WebGPURenderer({ ... });
      })
    );
  } else {
    resolve(new WebGLRenderer({ ... }));
  }
});

// wait for renderer to become available
rendererPromise.then(init);

function init () {
  // ... rest of your script
}
1 Like

Thank you for your guidance. I have reorganized my code, and the code is as follows:

let renderer;

const rendererPromise = new Promise((resolve, reject) => {
  if ( navigator.gpu ) {
    resolve(
      import('three/examples/jsm/renderers/webgpu/WebGPURenderer.js')
      .then(({default: WebGPURenderer}) => {
        return new WebGPURenderer({ canvas: canvas, antialias: true });
      })
    );
  } else {
    resolve(new THREE.WebGLRenderer({ canvas: canvas, antialias: true }));
  }
});



// wait for renderer to become available
rendererPromise
  .then((resolvedRenderer) => {
    init(resolvedRenderer);
  })
  .catch((error) => {
    console.error("rendererPromise 解决失败:", error);
  });

function init (resolvedRenderer) {
    renderer = resolvedRenderer
  // ... rest of your script
    renderer.outputColorSpace = 'srgb'
    renderer.setSize(sizes.width, sizes.height)
    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
    renderer.setClearColor('#555555')
    

It can work fine on different devices in the local network, but the renderer used by Chrome v113 on Windows is Webglrenderer.
1684964392472

Then when I tried to build it and deploy it on Vercel, an error occurred.

NodeMaterial.js:381 Uncaught (in promise) Error: NodeMaterial: Material “MeshBasicMaterial” is not compatible.

It seems to be a compatibility issue with the WebGPURenderer itself. I only used MeshBasicMaterial in the project, and the version of Three.js is r152.

By the way, the detection mechanism can work properly on browsers that do not support webgpurenderer.

Here’s my site on vercel: wip

Thank you for your guidance! I am just a beginner and have learned a lot.

2 Likes

I see that your website is running normally now.
Can you reveal how you managed to fix it?
Because I have encountered the same error
“NodeMaterial: Material “MeshBasicMaterial” is not compatible.” too

1 Like

I have encountered the exact same error. Have you fixed it?

have you fixed it?

No, I haven’t resolved the issue with webgprenderer yet, so I continued to use webglrenderer. I’m sorry for not replying to you for a long time

No, I haven’t resolved the issue with webgprenderer yet, so I continued to use webglrenderer. I’m sorry for not replying to you for a long time~ also,that website should be changed to this downto.vercel.app

It has been a while but i ran into the same problem (material "meshBasicMaterial) and it was an issue with the minification ! I seems to have been adressed in the last release of three :slight_smile: