PostProcess.updateEffect is called before the asynchronous shader loading, causing an error

Starting with Babylon.js version 7.20.0 (the latest at the time of writing),

using depth of field in DefaultRenderingPipeline fails to load the shader and cause an error.

It looks like @Deltakosh already added support for loading async shader source to the PostProcess class.

However, PostProcess’s updateEffect is a method that synchronously calls createEffect,
which is executed by the subclass or object it references and attempts to compile the shader before the shader source is loaded.
This is also why the depth of field post process doesn’t work.

I’ve seen code around PostProcess.updateEffect to address this, but it feels like the current approach to supporting WGSL is that programming to account for asynchronous processing will propagate from the bottom to the top of the engine.


If you’ve seen this result from searching the repository source for “_initShaderSourceAsync”, you know what I’m talking about.

In order for Babylon.js to support wgsl code in a sustainable and simple way, it would be nice to take async import promise as a parameter in Engine.createEffect and end all asynchronous network processes for loading shaders inside the createEffect function.

e.g.

let effect = engine.createEffect(
    shaderName,
    <IEffectCreationOptions>{
        attributes: attribs,
        // ...
        shaderLoadPromises: [
            import("../Shaders/default.vertex"),
            import("../Shaders/default.fragment")
        ]
    },
    engine
);

Since createEffect already has an implementation that loads and compiles code asynchronously, it should be easy to add an implementation that takes a Promise as a parameter.

Nevertheless, I wonder why the “_initShaderSourceAsync” mechanism was adopted. Was there a reason why createEffect couldn’t be made to take a Promise as a parameter?

It is not a bad idea at all.

When I chose the other approach I had to satisfy the following constraints:

  • NodeMaterial needs the data before calling createeffect as it uses the shader code to form the final string used for createEffect
  • I wanted to be as early as possible to potentially be in parallel with network calls (when you load files at the beginning for instance).

That being said I need to check what is going on with the Default Rendering pipeline and maybe for some cases I can keep my solution and use yours elsewhere.

1 Like

Do you have a repro of where it is not working?
works there: DefaultRenderingPipeline | Babylon.js Playground (babylonjs.com)

1 Like

This isn’t reproduced in Playground, because Playground already import all the side effects at load time, so the shader code is always in memory.

I’ll make a repository that reproduces this in no time. Please wait a few minutes

thanks!

I pushed that fix in the meantime:
Fix pipeline by deltakosh · Pull Request #15387 · BabylonJS/Babylon.js (github.com)

1 Like

I was late GitHub - noname0310/babylonjs-shaderloadtest

No worries! Let me know if my fix is ok for you !

1 Like

That makes sense, I hope the WGSL port goes well, thanks for the hard work on this

Thanks mate! It is a long and painful process but we will have a great wgsl support for the community:)

Thanks again for your report!

1 Like
Uncaught TypeError: Cannot read properties of null (reading 'isSupported')
    at get isSupported (postProcess.js:659:41)
    at get isSupported (postProcessRenderEffect.js:37:39)
    at get isSupported (postProcessRenderPipeline.js:51:60)
    at PostProcessRenderPipelineManager.update (postProcessRenderPipelineManager.js:104:31)
    at PostProcessRenderPipelineManagerSceneComponent._gatherRenderTargets (postProcessRenderPipelineManagerSceneComponent.js:67:58)
    at Scene.render (scene.js:3812:18)
    at eval (index.ts:45:34)
    at WebGPUEngine._renderFrame (abstractEngine.js:414:13)
    at WebGPUEngine._renderLoop (abstractEngine.js:397:26)
    at AbstractEngine._boundRenderFunction (abstractEngine.js:990:48)

I haven’t checked the reason yet, but I get another error in 7.20.1 release. The code is the same. GitHub - noname0310/babylonjs-shaderloadtest

On it!

1 Like

Fix: Fix isSupported by deltakosh · Pull Request #15393 · BabylonJS/Babylon.js (github.com)

Thanks again :slight_smile:

1 Like