Hello,
I suspect it’s an edge case scenario, but I’ll still give it a try.
In our code there happened a situation when stopRenderLoop
and runRenderLoop
were called within the same JS event loop, i.e. almost immediately one after another:
engine.stopRenderLoop(renderSceneFunction);
// some synchronous code
engine.runRenderLoop(renderSceneFunction);
This caused renderSceneFunction
to be called twice per frame, i.e. the “first” render loop wasn’t actually stopped.
Here’s a PG,
where render
function is called N times in 1 second of rendering (renderCount
variable),
but if you comment out the stopRenderLoop/runRenderLoop
calls it becomes ~ N/2.
I think the change was introduced here Cancel any pending animation frames on stopRenderLoop by carolhmj · Pull Request #14102 · BabylonJS/Babylon.js · GitHub (v6.14.2).
The reason is that _renderLoop
and runRenderLoop
methods both schedule another frame in this particular case:
_renderLoop() {
// ...
someRenderFunction();
// inside `renderFunction` there's a call to `stopRenderLoop`:
engine.stopRenderLoop(someRenderFunction);
// inside stopRenderLoop this flag is reset
this._renderingQueueLaunched = false;
// and _activeRenderLoops array is emptied
this._activeRenderLoops.splice(/*...*/);
// some synchronous code here, then still inside `renderFunction` render loop is resumed
engine.runRenderLoop(someRenderFunction);
// inside this function _activeRenderLoops array is filled
this._activeRenderLoops.push(renderFunction);
// and new frame is scheduled
this._frameHandler = this._queueNewFrame(/*...*/);
// END of `someRenderFunction`
// but this _renderLoop isn't over yet, it now checks for _activeRenderLoops which is not empty anymore
if (this._activeRenderLoops.length > 0)
// and then also schedules another frame
this._frameHandler = this._queueNewFrame(/*...*/);
Previously this._renderingQueueLaunched
wasn’t set to false
by stopRenderLoop
so new frame was only scheduled once.
I’d appreciate any input on that.
Thank you