0

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.

Krythic
  • 4,184
  • 5
  • 26
  • 67
  • Anything else running in the background? Also forget about immediate mode, it's deprecated, instead use shaders and VBOs – ratchet freak Nov 07 '14 at 11:38
  • @ratchetfreak Visual Studio and Google Chrome, and I am only using immediate mode for initial debug; I will be stripping it from my engine very soon. – Krythic Nov 07 '14 at 11:39
  • chrome can be an unexpected resource hog with the way it spawns processes for each tab, also VBO will be much faster and not use the same GL calls, so any insights you will get from this won't be valid once you cut out immediate mode – ratchet freak Nov 07 '14 at 11:45
  • While I don't have an answer for you, take note that far too many things could interfere in a process. Chrome uses hardware acceleration; window manager does so too, if compositing is enabled. Solve problem when you have one - thousands of FPS does nothing good and says nothing about performance. Drop heavy geometry to fall below vsync interval and measure it there. – keltar Nov 07 '14 at 11:47
  • @ratchetfreak I highly doubt that immediate mode right now would result in a sporadic 500fps increase and decrease. Granted, that would be a client side/software delimiter... – Krythic Nov 07 '14 at 11:47
  • @Krythic: First thing, use a more accurate time measurement like QueryPerformanceCounter (check MSDN docs). Second, measure and plot the time it takes for all frames over the time, this way you can see what is taking too much time. There are too many factors there to be taken into account but by doing that you can narrow down on one function that spikes inconsistanly (like swap buffers , or message processing , or other things) – Raxvan Nov 07 '14 at 11:53
  • @Raxvan I am currently looking into QueryPerfomanceCounter and boost::chrono. – Krythic Nov 07 '14 at 12:00

1 Answers1

2

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.

Ivan Aksamentov - Drop
  • 12,860
  • 3
  • 34
  • 61
  • Your update was an improvement. Now it only jumps around 150 frames or so, way better than the nearly 500-600fps that it was doing. – Krythic Nov 07 '14 at 12:13
  • I will accept you as the answer because you showed effort to what is probably an unsolvable question, and yet helped quite significantly. Thank you. – Krythic Nov 07 '14 at 12:23
  • Also, I believe this was indeed also worsened by running it along side 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. – Krythic Nov 07 '14 at 12:35
  • 3
    How drawing right after handling message is an improvement? What'll happen if there are two messages in queue? (one will be handled, the rest will be delayed until next frame). Handling all events before drawing is common and correct practice. – keltar Nov 07 '14 at 12:39
  • @keltar Oh, I dind't noticed well that it's `if` not `while` when was editing the initial snippet (even though I removed `else` =/). So dumb indeed. Fixed. – Ivan Aksamentov - Drop Nov 07 '14 at 18:51