requestAnimationFrame vs. runRenderLoop

For context, I’ve started using Codeium in Visual Studio. I sometimes try to talk about generative AI’s ability to write code, and I thought it would help to get more examples than just ChatGPT. Anyway, it had an observation that I lack the experience to evaluate, so I thought I’d throw it out for more experienced Babylon.js developers.

Following an example somewhere, I had code that looked something like (function and variable names changed due to proprietary code):

engine.runRenderLoop(() => {
    do_stuff();
    scene.render();
});

Note that a side effect of running do_stuff is that some rendering may change. For example, it displays the current time. It is not necessary for the rendering to occur when that happens. It would be enough to trigger it when the browser gets focus again.

Codeium suggested that instead of using runRenderLoop, I should use requestAnimationFrame. Its argument was that requestAnimationFrame saves resources by not running when the browser is not focused (so no one can see any animation that might be done). I noted that some of what is in do_stuff should be run even if there is no render event and asked if I could get both behaviors. While researching that, I found WebGPU + custom render loop not working

Anyway, the resulting code, which seems to be working:

        engine.runRenderLoop(do_stuff);
        const render_loop = () => {
            engine.beginFrame();
            scene.render();
            engine.endFrame();
            requestAnimationFrame(render_loop);
        };
        requestAnimationFrame(render_loop);

The idea being that this runs do_stuff at a predictable interval (e.g. sixty times a second) and render_loop as needed.

Is requestAnimationFrame the recommended way to trigger render?

Is it sensible to do things in runRenderLoop that should happen even if rendering does not occur? Or is this a bad way to use runRenderLoop? If it’s bad, is there a recommended alternative way to get that functionality.

I believe this engine function is the best answer

This is the best way. If you don’t need render, just stop it.

For those who find the previous reply unreadable, let me translate:

runRenderLoop calls requestAnimationFrame behind the scenes, as all renderings should. There is no benefit to calling requestAnimationFrame directly in the general case.

The linked code bit is where requestAnimationFrame is called. If you look up runRenderLoop in the same file, you can trace through to that QueueNewFrame method.

Codeium was wrong when it claimed that the runRenderLoop function (in the parameter) was called sixty times a second regardless of whether the window was in view. It’s only called by requestAnimationFrame.

This may further imply that my original code was correct and the revised code is unhelpful. It might even say that the revised code was incorrect, as it calls runRenderLoop without actually rendering (which is part of what I was asking). Answers to my questions, as best I understand them:

Not directly. Usually you’d want to invoke it through runRenderLoop which remains the recommended way to trigger render. If you don’t use runRenderLoop, you have to call engine.beginFrame and engine.endFrame manually.

No. Because that function (that is passed to runRenderLoop) will never get called unless rendering is supposed to occur.

This is a bad way to use runRenderLoop, as it doesn’t do that (run at a fixed interval regardless of whether render is needed). It may or may not also be problematic that it was invoking pre- and post-render activity without calling render. That (previously implicit) question remains unanswered. It’s probably not that problematic, as it’s possible to block rendering on a case-by-case basis in the passed function and no one is posting about problems that causes.

Apparently not officially. This is not to say that the functionality is impossible, only that it is out of scope of what Babylon.js does.

Apologies that my original questions were so difficult to understand. I had hoped that I provided sufficient context that if my premises were incorrect, someone could point that out directly. Apparently that hope was in vain. I’ll try to do better in the future.