How to detect the completion of initialization

After all my models are loaded via asset containers and their contents added to the scene, I still suffer up to 5 seconds delay before the models appear. The skybox and floor are already rendered so scene initialization was clearly finished.

I want to add a Loading overlay, but I need an event to hook so I can clear that overlay when all is finally ready. What is Babylon doing during that delay? Lazy-compiling shaders?

I generally use this observable.

    scene.onReadyObservable.add(e=>{
        console.log("do something")
    })

Of course you can also use custom loading screens,
This is the document Creating Custom Loading Screens | Babylon.js Documentation (babylonjs.com)

Nope, this is some additional delay above and beyond the onReadyObservable. That’s why I noted that the skybox and floor are already rendered. Once my scene is ready then I begin loading the models.

And I’ve timed that delay, from beginning to end of loading. They get added to the scene, and then there’s an additional delay of a few seconds until they become visible. Which is strange because this is a very fast machine w/ an RTX3080.

Once the load and then the post-load delay are over, the renderer unfreezes and FPS are terrific. But that post-load delay is killing me.

@brechindo can you share a repro ?

https://ultimator.snaponpromotion.com/build/KEXN724A/AQgU_wYLTwIkCBQCEQElCBQCNwEHCBQCPQELCBQCJAEjCBQCKQEBCBQCKQECCBQCKgEZCBQCKgEYCBQCJAEKCBQCJAEaCBQCAA

@sebavan
This is our worst-case scenario, nicknamed The Beast. You should see the framework load quickly with all its 2D elements and a white canvas.

Then the skybox and floor load, but in low res for a moment. Then they come in clear. That’s scene init.

Then several seconds later, the model appears. But the model loading only takes about 1s (timed with Date.now() in the console) including adding all the asset container assets to the scene, and THEN the rest of the delay is several additional seconds with no mouse control.

Finally the renderer unfreezes, the models appear, and everything is normal.

Everything is working fine for me as soon as the model is visible. Can you check in the dev tool if you have a really slow operation ?

Also, you could add custom marks in the devtools to help you with the timing measurement.

Are you using the prepass renderer directly or indirectly (using SSAO2, SSR, motion blur, sub-surface scattering, etc)?

It seems that there is an additional delay when using the prepass renderer, see Model load much slower with cascadedShadow and prepassRenderer - #5 by Evgeni_Popov.

I am looking into this.

1 Like

@sebavan “as soon as the model is visible” would be the key phrase there. The trouble is the whole site appears to freeze for a few seconds until the model is finally visible.

I cant use the perf analyzer on this problem thus far, because Babylon isnt initialized until there’s a scene to load and the freeze happens almost immediately then. By the time I can get the PA open, the freeze is over. When I reload the page, the PA automatically goes away.

Is there a better way to get into the PA? Some way I can code it to open automatically?

@Evgeni_Popov SSAO2, specifically the SSAO2RenderingPipeline, although I also access the prepass renderer to enable MSAA. See below:

        const ssaoRatio = {
            ssaoRatio: 0.5, // Ratio of the SSAO post-process, in a lower resolution
            blurRatio: 0.5// Ratio of the combine post-process (combines the SSAO and the scene)
        };

        const ssao = new SSAO2RenderingPipeline("ssao", scene, ssaoRatio, [cam]);
        ssao.samples = 16;  // default 8 shows weird buffering bug
        ssao.textureSamples = 4;
        //ssao.radius = 2; // default 2
        ssao.totalStrength = 1.3;
        ssao.expensiveBlur = false;

        scene.prePassRenderer!.samples = 4; // MSAA disabled by default (==1)

If you are using a shadow generator it could be the problem, it seems the compilation of the shaders done during the scene.isReady process don’t have the prepass renderer enabled, so when the scene is “ready” and should be displayed, new shader compilations take place.

I do have 2 lights for which I instantiate a ShadowGenerator each, during onSceneReady(). Which I guess means after the scene has been initialized by the renderer. That’s bad then? I should init lights and shadows before, not after, scene ready?


                const gen = new ShadowGenerator(256, light);
                gen.setDarkness(0.4);

                // PCF, because PCSS/"contact hardening" is expensive
                gen.usePercentageCloserFiltering = true;   // removes surface acnea
                gen.filteringQuality = 1.0;

                /*  PCSS disabled for now, costs too much time on startup
                    gen.useContactHardeningShadow = true;
                    gen.contactHardeningLightSizeUVRatio = 0.6;
                */

                return gen;

Yes, you should initialize them before calling scene.executeWhenReady, but because of the bug with the prepass renderer it may not be enough to avoid a delay in the rendering.

1 Like

This PR will make sure that everything is ready before scene.isReady returns true, even when using the pre-pass renderer:

3 Likes

Regarding the delay problem that occurs due to the use of the pre-pass renderer, it seems to be a problem with Angle when using the default backend (DirectX), I filed a bug :

https://bugs.chromium.org/p/chromium/issues/detail?id=1448494

2 Likes