High CPU usage when GLFW / OpenGL Window isn't visible
Asked Answered
I

3

8

I'm using GLFW so set up a Window with OpenGL. As i'm just started learning OpenGL and all the stuff around it, this might sound like a silly question, but why is the example program of GLFW using nearly 100% CPU when the Window is not actively displayed (minimized or hidden by another Window)?

Here is the GLFW exmaple, i'm running it on Mac OS with Xcode:

#include <GLFW/glfw3.h>
int main(void)
{
    GLFWwindow* window;

    if (!glfwInit())  /* Initialize the library */
        return -1;

/* Create a windowed mode window and its OpenGL context */
    window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
    if (!window)
    {
       glfwTerminate();
        return -1;
    }

/* Make the window's context current */
    glfwMakeContextCurrent(window);

/* Loop until the user closes the window */
    while (!glfwWindowShouldClose(window))
    {
        /* Render here */

        /* Swap front and back buffers */
        glfwSwapBuffers(window);

        /* Poll for and process events */
        glfwPollEvents();
    }

    glfwTerminate();
    return 0;
}
Interrupt answered 8/5, 2014 at 19:3 Comment(7)
You might consider using VSYNC, by the way - that will throttle your drawing thread considerably. Usually it is done with something more intelligent than a spinlock when you draw at high framerates, so this will effectively reduce CPU load. There is not much point rendering faster than you can push frames to the monitor unless you have super demanding input latency requirements.Murguia
Thanks for the VYSNC suggestion, i'm already doing glfwSwapInterval(1), i think that is enough?Interrupt
Yes, that is enough. I did not see that in your code anywhere, so I assumed you were using the default swap interval.Murguia
The above Code is just the Basic GLFW example, i dind't wanted to post my code, since i was trying to use the shortest way to explain the problem.Interrupt
@BastianSeeleib Did you find a solution to this issue? It is troubling me alsoWohlen
@MarcelCăşvan Yes, i used the glfwSetWindowIconifyCallback function to determine when the window is hidden and then slow my rendering loop down to ~5 fps via a simple sleep(). glfw.org/docs/latest/window.html#window_iconifyInterrupt
Problem with macOS is that when a window is not visible (f.e. occluded, or minified) v-sync is no longer working as it should. There is already an issue on GLFW regarding this problem: github.com/glfw/glfw/issues/680Monica
R
11

Your render loop is executed no matter what mimimization state of your window is.

If you want to stop rendering, you have to enhace the application logic a bit to track the state your window is in. GLFW supports user-defined a callback for such things with glfwSetWindowIconifyCallback() so your application can get noticed when the window is minimized or restored. You can the decide to stop the render loop, and can use glfwWaitEvents() to wait for something to happen (like the window being restored) without using all available CPU time.

Rehearsal answered 8/5, 2014 at 19:25 Comment(4)
Thanks for the answer, as my render-loop needs to run all the time, except when the window is not displayed, glfwSetWindowIconifyCallback() is exactly what i searched for.Interrupt
But why is this happening when minimised and not when the window is shown? I am getting the same behaviour. And there has to be a logical explanation and a solution to this issue.Wohlen
In OS X, neither glfwSetWindowIconifyCallback or glfwGetWindowAttrib(window, GLFW_VISIBLE) is working when the window is behind another window, but not minimized. The CPU usage still skyrockets, however.Pulpwood
Yeah, for now I'm using glfwGetWindowAttrib(window, GLFW_FOCUSED), but it may not fit your purpose if you need to see what's going on when the app is visible in the background.Fernanda
I
4

Maybe start doing something?

Or use glfwWaitEvents(); instead of glfwPollEvents(); to block when there isn't new events.

The documentation explains it on the first step : http://www.glfw.org/docs/latest/quick.html

Involution answered 8/5, 2014 at 19:26 Comment(1)
Could you add a brief example or further explanation?Soviet
S
3

NSOpenGLContext::flushBuffer is non blocking if the window is not visible to the user (for instance, there another window in front of it). Since glfwSwapBuffers does just call this function, it becomes non blocking in this situation. I'm not sure what options we have to avoid consuming 100% CPU in this case, except using a Core Video display link.

From here: https://github.com/glfw/glfw/issues/680

OS X ignores the NSOpenGL swap interval when the window is obscured. No other OS does this. I will look into working around this with display link at some point. If that doesn't work, I don't think there's anything GLFW can do.

Steck answered 28/2, 2017 at 22:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.