The render loop logic in Qt 3D has to be redesigned since what we have there today (and used by Scene3D and Studio3D) is broken when it comes to Qt Quick or widget integration (Q3DSWidget works similarly to Scene3D and Studio3D).
Proper Qt Quick integration means that when we call renderSynchronous(), Qt 3D must render the next frame. Neither not doing anything nor waiting for any N > 0 time is acceptable since renderSyncronous is called when Qt Quick renders a frame, meaning there will be a swap and vsync throttling afterwards - if there is no 3D content generated in that frame then it means there is just no way to get a 60 FPS 3D view that runs in lockstep with the 2D content.
Various Qt 3D Studio scenes are busted due to this and run with varying degrees of smoothness - it is not unlikely to get a !queueIsComplete or even a queueIsEmpty. The blocking mode is useless (the Qt Quick render thread (which may be the main thread) must not be blocked, it does not handle queueEmpty, and arbitrary timeouts are fragile anyway)
Consider this. Here we are running with a Studio3D and the 'windows' render loop so Qt Quick and the renderSynchronous() calls are made on the main thread. The GL impl is NVIDIA which presumably throttles in GL calls (not on swapBuffers) hece the render 15 and swap 0 in the scenegraph logs. That's fine.
The bad things are: why does renderSynchronous take 15-16 ms (when it actually does something) when it then gets followed by Qt Quick's rendering that takes the same (we need to block somewhere to vsync true but together that's like 33 ms...)? Why do we skip invoking frame actions? And that we skip 3D rendering in some frames, as outlined above.
In the end we end up with something like the following. Note the min and max values below the avg and the graph.
(no threaded render loop)
(threaded render loop, the default on most systems)
the behavior is definitely different here as renderSynchronous does not take 15-16 ms in this setup (when it's on the dedicated Quick render thread) yet we still lose time on the main thread somewhere.