BABYLON.WebGPUEngine and OffscreenCanvas: Roadmap for Support?

Hi again,

As my game project progresses with effects, animations, and many meshes, I need to work more closely with the metal :slight_smile:

I’ve been examining Babylon.WebGPUEngine and noticed its constructor currently accepts (canvas: HTMLCanvasElement, options?: WebGPUEngineOptions).

Is there a way to use an OffscreenCanvas with the WebGPUEngine currently? Also, are there any plans to implement this feature?

Thank you again for all your excellent work you are doing :partying_face:

WebGPU in a Worker example: https://webgpu.github.io/webgpu-samples/samples/worker

1 Like

cc @Evgeni_Popov, I guess it should be pretty similar to adding the correct typings.

1 Like

This PR adds the support for OffscreenCanvas in the WebGPUEngine constructor:

4 Likes

Thank you :blush:

WebGPU won’t display anything on the offscreencanvas, and it works fine for WebGL2. Do we have any Babylon.WebGPUEngine with OffscreenCanvas ? I would love to have a look at that :slight_smile:

Here is the setup for Babylon.Engine:

if (WEBGPU_ENABLED) {
    const engine = new BABYLON.WebGPUEngine(this.offscreenCanvas);
    void engine.initAsync().then(() => {
        this.engine = engine;

        this.loadScene();
    });
}
else {
    this.engine = new BABYLON.Engine(this.offscreenCanvas, true);

    this.loadScene();
}

The configuration for the scene:

BABYLON.Scene(this.engine, { useGeometryUniqueIdsMap: true, useClonedMeshMap: true, useMaterialMeshMap: true });

and a BABYLON.ArcRotateCamera and a BABYLON.HemisphericLight

Update: I noticed scene.clearColor = BABYLON.Color4.FromHexString(#AAAAAA); has no effect for WebGPUEngine and works as expected for WebGL

It does work for me in this PG:

After 1s, the offscreen canvas will be converted to a data url, and this url will be used as the source for an IMG element displayed at the top/right of the screen.

scene.clearColor = BABYLON.Color4.FromHexString("#AAAAAA"); does work (see PG).

Thanks for the confirmation and I will look into the issue and report back when I found the issue on my end :slight_smile:

I found the issue, and it seems that WebGPU requires to use:

engine.runRenderLoop(() => { scene.render(); });  //Works for WebGPU/WebGL

while WebGL can use a render outside the runRenderLoop:

engine.stopRenderLoop();
setInterval(() => { scene.render(); }, 100); //works only for WebGL

I have made an demo about it here: BABYLON.JS web worker

Is this behavior by design ?

In WebGPU, everything should happen between engine.beginFrame() / engine.endFrame() (it happens that WebGL doesn’t do anything critical in these functions, that’s why you can omit them - but it’s still better to call them). When using a render loop, it is done for you. Else, you should do these calls yourself:

engine.beginFrame();
scene.render();
engine.endFrame();
4 Likes

Superb! That fixed it :slight_smile:

Thank you

I’ve added WebGPU support now and this is my notes:

When I added support for WebGPU, application to loading my Babylon engine into a worker and the canvas as an OffscreenCanvas, I encountered a few issues that did not occur with WebGL:

  • Since my canvas may resize, I had to use Babylon.WebGPUEngine.resize(true); otherwise, it would not display and would print numerous warning messages in the console.

  • For my custom render method, I had to add beginFrame, render, endFrame.

  • I can’t set Babylon.Scene.autoClearDepthAndStencil to false in WebGPU mode

  • WebGPU shaders strictly require that attributes be declared, for example: ‘Vertex attribute slot 1 used in ([ShaderModule], [EntryPoint “main”]) is not present in the VertexState.’

WebGL remains my default renderer as WebGPU does not significantly improve performance in compatibility mode. Some of my games run in non-compatibility mode, where I see a performance gain, but it is not yet ready for production release.

1 Like

For 1/ and 2/, it’s more like it should also be done in WebGL, but that for some reasons it still works without doing it (for 2/, it works because WebGL does nothing substantial in being/end frame).

For 3/, I’m not sure why it would not work… If you have a repro, we can have a look.

For 4/ it’s expected, WebGPU is more strict than WebGL in this regard.

I’m happy to know that you can get some performance gain when using the non-compatibility mode in WebGPU!

1 Like