Sign in to follow this  

Help: Low-level timing oddities.

This topic is 3856 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello smart beings from GameDev.net. I need some assistance in solving my problem. I am making an engine, though I call it more of a framework rather than an engine because most of the things in it are just wrappers and no major subsystem existing yet. Anyway, I'm at this point of making an FPS (frame rate) counter. This one seems to be odd because I keep on getting 41FPS on my counter and not 60! Note that I have a 3.0Ghz (OC'ed) core2duo system, and I am just rendering four simple lines forming a crosshair at the center and nothing else! So, I'm doubting that my FPS computation is wrong since if I set my m_FPSControl (my delay rate for busy-waiting loop) to 75, I get an FPS of 60 and above. Is there something wrong on my code? InterfaceGame methods:
U32 InterfaceGame::GetFPS()
{
    return m_FPS;
}
    
U32 InterfaceGame::GetFPSCount()
{
    return m_FPSCount;
}
    
U32 InterfaceGame::GetMsPF()
{
    return m_MsPF;
}

inline void InterfaceGame::SetFPS( U32 p_MyFPS )
{
    m_FPS = p_MyFPS;
    m_FPSControl = 1000 / m_FPS; // looks right to me
}

void InterfaceGame::GameSyncStart()
{
    m_TimeStart = App::GetTick();
}

void InterfaceGame::GameSyncFinish()
{
    while( ( App::GetTick() - m_TimeStart ) < m_FPSControl );
    m_MsPF = App::GetTick() - m_TimeStart;
    ++m_FPSFrames;
    m_FPSTickAccumulator += m_MsPF;
    if( m_FPSTickAccumulator > 1000 )
    {
        m_FPSCount = m_FPSFrames;
        m_FPSFrames = 0;
        m_FPSTickAccumulator = 0;
    }
}
Before game loop:
g_pGame->SetFPS( 60 );
My main game loop somewhere:
{
    g_pGame->GameSyncStart();

    ...

    g_pGame->GameSyncFinish();

    SwapBuffers( g_App.AppDeviceContext );

    if( App::IsFPSDisplayOn() && !App::IsFullscreen() )
    {
        std::string StringTemp = App::GetGameName( TRUE );
        StringTemp += " - ";
        StringTemp += ToString( g_pGame->GetFPSCount() );
        StringTemp += "/";
        StringTemp += ToString( g_pGame->GetFPS() );
        StringTemp += " FPS;  ";
        StringTemp += ToString( g_pGame->GetMsPF() );
        StringTemp += " MsPF";
        SetWindowText( g_App.AppWindow, StringTemp.c_str() );
    }
}
Anyone? -edit- corrected a code to prevent confusion. [Edited by - AndreiVictor on May 26, 2007 12:29:32 PM]

Share this post


Link to post
Share on other sites
Couple of questions: Where are you calling SetFPS? What exactly are you trying to accomplish with m_FPSControl?

It looks like m_FPSControl is a way to lock the framerate, but it it dynamic with the current framerate. I think its forcing the frame to wait as much time as it took to finish the previous frame. This could be a problem when your framerate spikes. You probably want m_FPSControl to be constant.

Can't help you much more if I don't see where you call SetFPS :)

G'luck.

Share this post


Link to post
Share on other sites
Hi Blaze, thanks for replying. The...

g_pGame->SetFPS( 60 );

...is set right before entering the main game loop. I've edited the code to make that clear. So, with SetFPS, it will compute for the right "constant" for the busy-waiting loop. However, you know what the problem is. :)

So to further clarify:
SetFPS( 60 ) will compute for the amount of time a single frame should take at the least.

So why is it I'm having 41 frames?
I asked a friend of mine to test on his machine which is 2.4Ghz line. We have exact frame rate locked to 41fps.

Share this post


Link to post
Share on other sites
m_FPSControl = 1000 / m_FPS



This is integer division. So you won't get fractional part regardless of what type m_FPSControl is.

I'm not sure if this has anything to do with it, but just to make sure. The rounding here could throw you off.

Share this post


Link to post
Share on other sites
Quote:
Original post by Antheus
*** Source Snippet Removed ***

This is integer division. So you won't get fractional part regardless of what type m_FPSControl is.

I'm not sure if this has anything to do with it, but just to make sure. The rounding here could throw you off.


I actually have it like that at the beginning before I rewrote it to that. Simply because I am expecting milliseconds as the final result for m_FPSControl. Looking at that code m_FPSControl does look suspicious in terms of mathematical formulation. My head is not working right, it's 2 AM here at my place.

1000ms / ( 60 frames / 1000ms) does not result to a single ms unit right?

Share this post


Link to post
Share on other sites
I'm thinking that your graphics API is waiting for VSync. The SwapBuffers call may be waiting to the next VSync... but it is doing it AFTER you wait 16ms to lock to 60 fps.

See if you can set the presentation interval to immediate. That is what D3D calls it, finding the OpenGL equivalent shouldn't be difficult.

Hope that helps.

Share this post


Link to post
Share on other sites
Quote:
Original post by AndreiVictor
1000ms / ( 60 frames / 1000ms) does not result to a single ms unit right?


You aren't doing that though, are you? In SetFPS, it executes "1000 / 60" and sets m_FPSControl to 16. So now your spinloop is waiting for 16ms instead of 16.7. If anything, this would speed up your fps.

Share this post


Link to post
Share on other sites
1) The resolution of your App::GetTick is probably only 10..15 ms. (use winmm!timeBeginPeriod to improve it)
2) You really don't want to limit framerate via spin loop. Power/thermal considerations aside, it is a waste of CPU time and just not necessary. See http://www.mindcontrol.org/~hplus/graphics/game_loop.html

HTH+HAND

Share this post


Link to post
Share on other sites
blaze02 was right. It is the Vsync in swap buffers! I removed the spinloop in my code and just measured the frames and found out it is already fixed to 60fps.

I know Vsync is good, but sometimes I would like to let the user/developer have the control over it because the goodness of vsync can be a case to case thing on different computers.

Thanks all for leading me to this conclusion! :)

Share this post


Link to post
Share on other sites

This topic is 3856 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this