I’m working on a multiscreen project which should be cross platform macOS/Windows.
For multiple windows management I followed the “oneAppMultiWindow” example, which in this specific case fits better than the two-apps / two-windows scheme I used other times.
Everything works nicely, except that frame rate with two windows open is sensibly lower than the frame rate with only one window open, even when I do not draw a single thing.
When I run the app commenting out all the drawing code I get around 130 fps but when I close the window in second screen the frame rate jumps up over 200 fps.
I keep vertical sync disabled because with vertical sync enabled I get always close to 60 fps but with a lot of jitter and the visual result is a 30 fps looking laggy animation.
It’s a consistent behaviour on Visual Studio/Windows 10 across a couple of quad core i7 HP and a six-core i7 MSI gaming machine. While on Xcode/MacOS both in an old macBookPro Retina i7 2013 and a “trashcan” MacPro it doesn’t matter whether the second window is open or not, I get always ridiculously high fps and fluid animation.
I tried switching to the two-windows / two-apps model but nothing changes.
It seems that on Windows some major overhead is generated somewhere when two ofAppBaseWindow are active, and it tends to get worse when windows are big, even with no drawing code. Sharing gl context between windows or not does not make a difference at all.
I also had a little deeper look in GLFW and OpenGL, but I’m not able to find a meaningful explanation. Do anyone have any idea?.. Thank you in advance.
Did you try to run it on windows in Release mode instead of Debug? Running on debug in windows is a very common cause of lowered FPS.
Yes, the frame rates I was talking about are in Release mode. Debug mode actually is much slower.
There’s another issue of Windows release, which I never noticed on macOS: if you make larger windows the frame rate drops the same way of having two windows open or even worse.
I realized about that while I was trying to solve the two windows frame rate drop. I had the idea to make a big undecorated window across the screens and then use the two screens rectangles as two windows. But also that way I got more or less the same frame rate drop.
I suppose there’s something involving the windows memory allocation that behaves not as expected. It should be entirely managed by OpenGL in the GPU, right? So why allocating more screen space has a side effect on CPU? AFAIK GLFW/openFrameworks manage only the front/back buffer switching and window events, so CPU usage should not be affected by windows size. Moreover, in macOS this does not happen, so it leads me to suspect something is going not so straight in Windows build. But maybe also I’m on the wrong way…
I cant really tell as I have not deployed to windows for a while. Yes, all the drawing is managed by openGL and the GPU, but if you have a big load on the gpu it will slow down the whole rendering process. If you have set
ofApp::setup it will “detach” the call to
ofApp::draw. When these are detached or unsynced, these still run on the same thread but update calls it self immediately after finishing or calls
draw if the GPU has “said” that it is ready for rendering a new frame. In this mode you can actually see if the load is being applied to the CPU or the GPU. measure the time between successive calls to update and successive calls to draw and that might give you a clue.
On the contrary, when it VerticalSync is set to true (the default), each call to draw is preceded by a single call to update, thus these are in sync. The rate at which it will happen is determined by the gpu. So if this is your case and the load is on the GPU, it will also slow down the calls to update.
Thank you Roy, now I fully understand the underlying mechanism. Until now I supposed that draw and update were two callbacks from the same main loop, just to keep things clean and to divide drawing code from other stuff. Of course, things being as you explained, I’ll have better a look at timing balance between draw and update.
great. Although, you must notice that these two run on the same thread, and on the same loop actually.