Search code examples
c++openglframe-rate

OpenGL Inconsistent Framerate


I have been creating/porting a game that I was making in C# over to C++ and when I started to look at my frames per second I noticed something odd going on.

I was originally programming my game in C#, and the frame rate was always pretty consistent. When I had VSync turned on, I would get a solid 60fps, and without, somewhere around 600-700 or so. It was always pretty much a static number. Now, in a c++ environment, I notice that the frame rate dips quite a bit and appears highly erratic/inconsistent(pretty sure this has something to do with my implementation).

I was going to set up a log and let the application run while capturing the frame count, however, this resulted in a frame rate drop and so I decided against trying to show you guys via that route. Instead, I will just say that when the application starts, the frame rate shows as 0 for about 20ms, then jumps up to about 2500fps. The application will then jump around +500 or -500, and sometimes even effectively double to where it is nearly 4000fps. Using OpenTK, the frame rate always showed as 60fps on first start up(Vsync enabled) and didn't have the issue of showing 0fps for a few ms.

I am quite certain that the frame rate is dropping, increasing, dropping, increasing, etc. Which, to me, looks like a variable rolling around when it hits a maximum value.

I should also probably mention that I am not using an OpenGL library. I wanted to write it all from the ground up, which I have been doing quite successfully. I just don't know why the frame rate is so inconsistent.

Here is the primary class where everything is initialized and the frame rate itself is counted. Hopefully someone can help me spot something that I did wrong. I apologize in advance because the class is about 220 lines of code.

http://pastebin.com/tV4Sd2K3

I am only rendering one triangle, which is done via immediate mode.

Here are also three quick pictures to further demonstrate what I am talking about: This one lasts for about 20-30ms, then goes up to over 2000fps.

enter image description here

This one shows an abrupt low spike(I am literally doing nothing but rendering a triangle!)

enter image description here

And a high spike, again, only rendering 1 triangle. nothing else is happening!

enter image description here

Those pictures are just a quick example, it is sometimes far worse or better.

Final Thoughts after receiving help: This issue was caused by both my implementation and debugging within visual studio. I created a release build, closed everything out, and ran the executable. The deviation of frames were only about +-50; it hangs healthily around 2700-2800fps. So, lesson learned: debugging in Visual Studio is NOT WYSIWYG.


Solution

  • timeGetTime() is a terribly wrong way to measure time. So I doubt you have accurate FPS values in first place. Use boost::chrono (note, that std::chrono is currently doesn't provide good accuracy in Visual Studio 2013 implementation) or native QueryPerformanceCounter.

    Another thing, which is actual FPS jump problem, is your main loop:

    while (isGameRunning)
    {
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            if (msg.message == WM_QUIT)
            {
                break;
            }
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else
        {
            draw();
        }
    }
    

    You only draw if you don't have Win32 messages to proceed (when PeekMessage() returns false). So with any message you have frames that are lost.

    You should do it this way:

    while (isGameRunning)
    {
        while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE | PM_NOYIELD)) // add PM_NOYIELD
        {
            // Move it to `WndProc`.
            // Break loop by setting `isGameRunning` to `false`
            //if (msg.message == WM_QUIT)
            //{
            //  break;
            //}
            TranslateMessage(&msg);
            DispatchMessage(&msg);
    
        }
        // Draw unconditionnaly
        draw();
    }
    

    HTH.