Mind of its own FrameRate

Started by
5 comments, last by Dissipate 11 years, 5 months ago
Hi please help

I am getting some strange results from my framerate calculation. It seems to have a mind of its own. It wants to stay at about 60 fps even if I set it to 80fps. It does run though if I set it to 50fps.

I am getting smooth movement at 60fps but at 50fps the waiting part kicks in and starts to jitter the movement. I have given the entire while loop.

it works I've tested it but I dont know why it stays at 60 fps. Please help I'm at my wits end. Here is what I have done so far...

[source lang="cpp"] MSG msg;
DWORD ticks = GetTickCount() / 1000;
DWORD ticksMS = GetTickCount();
ticks = 0;
int iFrame = 0; // the current frame
int iFrameRate = 60; // limits the framerate
g_uFrameRate = 0; // global framerate
long iWaited = 0; // length of time waited
int iNumSecs = 0; // number of seconds gone by in game loop
char c[80]; // used as debug text
string s;
DWORD fDelta = 0.0f;
FILE* pFile;
char buffer[100];
int iFrameCycles = 0;
fopen_s (&pFile, "myfile.txt" , "w");
if (pFile == NULL) perror ("Error opening file");
while (g_App.GetD3DStatus())
{
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if (msg.message == WM_QUIT)
break;
if (KEY_DOWN(VK_ESCAPE)) PostMessage(hWnd, WM_DESTROY, 0, 0);
if (KEY_DOWN(VK_MBUTTON)) PostMessage(hWnd, WM_DESTROY, 0, 0);
// only run if more than 1 second has passed
if (ticks < (GetTickCount() / 1000))
{
// save the framerate to tell CApplication, sprites and meshes
g_uFrameRate = iFrame;
// values
iWaited = 0; // reset the amount of time waited
ticks = GetTickCount() / 1000; // rest ticks to the current time
ticksMS = GetTickCount();
iFrame = 0; // reset the number of frames to zero
iNumSecs += 1; // increment the number of secs gone by
iFrameCycles = 0; // the number of revolutions per second
}
// pause if we have rendered more than the framerate in 1 sec
if (iFrame >= iFrameRate)
{
// calc amount of ms left over
fDelta = 1000 - (GetTickCount() - ticksMS);
}
else
{
// check for user input
g_App.DetectInput();
// render
g_App.Render();
//Sleep(20);
// incrememnt the frame number
iFrame++;
} // endelse
iFrameCycles++;
} // end while (g_App.GetD3DStatus())
fclose (pFile);[/source]

also here is my Movement code:

[source lang="cpp"] void CShape::Orbit(float fX, float fY, float fZ)
{
// calc xyz velocity's cirular points
m_fXV = (float)(sin(fX) * 12.0f) * 20.0f;
m_fYV = 0;
m_fZV = (float)(cos(fZ) * 25.0f) * 20.0f;

// set the spacial coords equal to triad velocities
// make sure that there is no divide by zero and
// divide the velocity by the current framerate to give
// the per second unit of movement.
if (m_fXV != 0)
m_fX = m_fXV * fT;
if (m_fYV != 0)
m_fY = m_fYV * fT;
if (m_fZV != 0)
m_fZ = m_fZV * fT;

// apply this to a matrix
D3DXMatrixTranslation(&m_matTranslate, m_fX, m_fY, m_fZ);
}// Orbit[/source]
Advertisement
it works I've tested it but I dont know why it stays at 60 fps.[/quote]

a few lines in the code...

int iFrameRate = 60; // limits the framerate[/quote]

Jokes aside, I think the problem is that your Render() method calls the D3D Present() function, which pushes the current frame to the screen - this may be subject to its own framerate limitation, for instance vertical synchronization. Try taking that call out and see if the loop runs at the correct rate now, if not, try removing functions one by one until you locate the problem.

Also, GetTickCount() is not very accurate, so you might observe jitter beyond 40 fps or so, the "improved" counter is QueryPerformanceCounter/Frequency.

“If I understand the standard right it is legal and safe to do this but the resulting value could be anything.”

Okay can i suggest something? I think you should look into the Windows API high performance timer.
Because looking at your code the way you calculate frame rate seems to be all over the place.

Basically using a couple methods namely: QueryPerformanceFrequency(LARGE_INTEGER); and QueryPerformanceCounter(LARGE_INTEGER)

You can find both the DeltaTime and TotalTime of the application instance. Then using those values you can calculate FramePerSecond and everything else over the moon.

An example of this can be found here http://mengine.googl...c/GameTimer.cpp
written by Frank Luna writer of the "Introduction to 3D game programming using DirectX" series.

Look at it closely and see essentially what is being done in each function.

Then look at the following function that uses the GameTimer class:


void D3DApp::CalculateFrameStats()
{
// Code computes the average frames per second, and also the
// average time it takes to render one frame. These stats
// are appended to the window caption bar.
static int frameCnt = 0;
static float timeElapsed = 0.0f;
frameCnt++;
// Compute averages over one second period.
if( (mTimer.TotalTime() - timeElapsed) >= 1.0f )
{
float fps = (float)frameCnt; // fps = frameCnt / 1
float mspf = 1000.0f / fps;
std::wostringstream outs;
outs.precision(6);
outs << mMainWndCaption << L" "
<< L"FPS: " << fps << L" "
<< L"Frame Time: " << mspf << L" (ms)";
SetWindowText(mhMainWnd, outs.str().c_str());

// Reset for next average.
frameCnt = 0;
timeElapsed += 1.0f;
}
}


Again ALL CREDIT TO FRANK LUNA.

This function calculates the frames per second and displays it to the application window title bar.

Now limiting the frame rate to 60 shouldn't be hard once you have a nice object oriented way to calculate the frames per second of your application.
I'm sure it's a V-Sync issue. You're graphics setting is probably set to V-Sync enabled, so you won't update your screen faster than your monitor's V-Sync (which is typically 60 HZ). Disable that "feature" and you're framerate should go higher.

My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

Thank you to each one of you.

I'm sure it's a V-Sync issue. You're graphics setting is probably set to V-Sync enabled[/quote]
I dont know how to set the V-Sync, but my research took me to msdn.microsoft.com/en-us/library/windows/desktop/bb173393%28v=vs.85%29.aspx also click the link at the bottom which talks about 'D3DSWAPEFFECT enumeration'
Mine is D3DSWAPEFFECT_DISCARD.

I have included to files which are the output of the framerate calc. the first is windowed the second is fullscreen. Notice the windowed one keeps going back to 60fps.

WINDOWED:

second = 0 fps = 0 delta (ms) = 0 iFrameCycles = 0
second = 1 fps = 46 delta (ms) = 0 iFrameCycles = 46
second = 2 fps = 60 delta (ms) = 0 iFrameCycles = 60
second = 3 fps = 60 delta (ms) = 0 iFrameCycles = 60
second = 4 fps = 60 delta (ms) = 0 iFrameCycles = 60
second = 5 fps = 60 delta (ms) = 2 iFrameCycles = 3484
second = 6 fps = 60 delta (ms) = 18 iFrameCycles = 4340
second = 7 fps = 60 delta (ms) = 17 iFrameCycles = 1338
second = 8 fps = 60 delta (ms) = 17 iFrameCycles = 1548
second = 9 fps = 60 delta (ms) = 17 iFrameCycles = 2290
second = 10 fps = 60 delta (ms) = 17 iFrameCycles = 1982
second = 11 fps = 60 delta (ms) = 17 iFrameCycles = 3684
second = 12 fps = 60 delta (ms) = 17 iFrameCycles = 2891
second = 13 fps = 60 delta (ms) = 18 iFrameCycles = 4049
second = 14 fps = 60 delta (ms) = 17 iFrameCycles = 5430
second = 15 fps = 60 delta (ms) = 1 iFrameCycles = 16662
second = 16 fps = 60 delta (ms) = 17 iFrameCycles = 9202
second = 17 fps = 60 delta (ms) = 17 iFrameCycles = 5426
second = 18 fps = 60 delta (ms) = 17 iFrameCycles = 7609
second = 19 fps = 60 delta (ms) = 18 iFrameCycles = 5890
second = 20 fps = 60 delta (ms) = 17 iFrameCycles = 7377
second = 21 fps = 60 delta (ms) = 17 iFrameCycles = 6118
second = 22 fps = 60 delta (ms) = 17 iFrameCycles = 5243
second = 23 fps = 60 delta (ms) = 17 iFrameCycles = 6329
second = 24 fps = 60 delta (ms) = 18 iFrameCycles = 16050
second = 25 fps = 60 delta (ms) = 2 iFrameCycles = 16479
second = 26 fps = 60 delta (ms) = 17 iFrameCycles = 14001
second = 27 fps = 60 delta (ms) = 17 iFrameCycles = 12259
second = 28 fps = 60 delta (ms) = 17 iFrameCycles = 5991
second = 29 fps = 60 delta (ms) = 17 iFrameCycles = 11231
second = 30 fps = 60 delta (ms) = 18 iFrameCycles = 3907


FULLSCREEN:

second = 0 fps = 0 delta (ms) = 0 iFrameCycles = 0
second = 1 fps = 46 delta (ms) = 0 iFrameCycles = 46
second = 2 fps = 60 delta (ms) = 0 iFrameCycles = 60
second = 3 fps = 60 delta (ms) = 0 iFrameCycles = 60
second = 4 fps = 60 delta (ms) = 0 iFrameCycles = 60
second = 5 fps = 60 delta (ms) = 2 iFrameCycles = 3484
second = 6 fps = 60 delta (ms) = 18 iFrameCycles = 4340
second = 7 fps = 60 delta (ms) = 17 iFrameCycles = 1338
second = 8 fps = 60 delta (ms) = 17 iFrameCycles = 1548
second = 9 fps = 60 delta (ms) = 17 iFrameCycles = 2290
second = 10 fps = 60 delta (ms) = 17 iFrameCycles = 1982
second = 11 fps = 60 delta (ms) = 17 iFrameCycles = 3684
second = 12 fps = 60 delta (ms) = 17 iFrameCycles = 2891
second = 13 fps = 60 delta (ms) = 18 iFrameCycles = 4049
second = 14 fps = 60 delta (ms) = 17 iFrameCycles = 5430
second = 15 fps = 60 delta (ms) = 1 iFrameCycles = 16662
second = 16 fps = 60 delta (ms) = 17 iFrameCycles = 9202
second = 17 fps = 60 delta (ms) = 17 iFrameCycles = 5426
second = 18 fps = 60 delta (ms) = 17 iFrameCycles = 7609
second = 19 fps = 60 delta (ms) = 18 iFrameCycles = 5890
second = 20 fps = 60 delta (ms) = 17 iFrameCycles = 7377
second = 21 fps = 60 delta (ms) = 17 iFrameCycles = 6118
second = 22 fps = 60 delta (ms) = 17 iFrameCycles = 5243
second = 23 fps = 60 delta (ms) = 17 iFrameCycles = 6329
second = 24 fps = 60 delta (ms) = 18 iFrameCycles = 16050
second = 25 fps = 60 delta (ms) = 2 iFrameCycles = 16479
second = 26 fps = 60 delta (ms) = 17 iFrameCycles = 14001
second = 27 fps = 60 delta (ms) = 17 iFrameCycles = 12259
second = 28 fps = 60 delta (ms) = 17 iFrameCycles = 5991
second = 29 fps = 60 delta (ms) = 17 iFrameCycles = 11231
second = 30 fps = 60 delta (ms) = 18 iFrameCycles = 3907


FULSCREEN @80fps (aimed at but it doesnt increase):

second = 0 fps = 0 delta (ms) = 0 iFrameCycles = 0
second = 1 fps = 1 delta (ms) = 0 iFrameCycles = 1
second = 2 fps = 62 delta (ms) = 0 iFrameCycles = 62
second = 3 fps = 60 delta (ms) = 0 iFrameCycles = 60
second = 4 fps = 60 delta (ms) = 0 iFrameCycles = 60
second = 5 fps = 61 delta (ms) = 0 iFrameCycles = 61
second = 6 fps = 60 delta (ms) = 0 iFrameCycles = 60
second = 7 fps = 60 delta (ms) = 0 iFrameCycles = 60
second = 8 fps = 60 delta (ms) = 0 iFrameCycles = 60
second = 9 fps = 60 delta (ms) = 0 iFrameCycles = 60
second = 10 fps = 61 delta (ms) = 0 iFrameCycles = 61
second = 11 fps = 61 delta (ms) = 0 iFrameCycles = 61
second = 12 fps = 60 delta (ms) = 0 iFrameCycles = 60
second = 13 fps = 60 delta (ms) = 0 iFrameCycles = 60
second = 14 fps = 60 delta (ms) = 0 iFrameCycles = 60
second = 15 fps = 61 delta (ms) = 0 iFrameCycles = 61
second = 16 fps = 60 delta (ms) = 0 iFrameCycles = 60
second = 17 fps = 60 delta (ms) = 0 iFrameCycles = 60
second = 18 fps = 60 delta (ms) = 0 iFrameCycles = 60
second = 19 fps = 61 delta (ms) = 0 iFrameCycles = 61
second = 20 fps = 60 delta (ms) = 0 iFrameCycles = 60
second = 21 fps = 61 delta (ms) = 0 iFrameCycles = 61
second = 22 fps = 60 delta (ms) = 0 iFrameCycles = 60
second = 23 fps = 60 delta (ms) = 0 iFrameCycles = 60
second = 24 fps = 61 delta (ms) = 0 iFrameCycles = 61
second = 25 fps = 60 delta (ms) = 0 iFrameCycles = 60
second = 26 fps = 60 delta (ms) = 0 iFrameCycles = 60
second = 27 fps = 60 delta (ms) = 0 iFrameCycles = 60
second = 28 fps = 60 delta (ms) = 0 iFrameCycles = 60
second = 29 fps = 61 delta (ms) = 0 iFrameCycles = 61
second = 30 fps = 60 delta (ms) = 0 iFrameCycles = 60


An example of this can be found here http://mengine.googl...c/GameTimer.cpp
written by Frank Luna writer of the "Introduction to 3D game programming using DirectX" series[/quote]
@Debunez: Thanks I'm ordering the book. I am looking through the timer code and trying to understand it.

so you won't update your screen faster than your monitor's V-Sync (which is typically 60 HZ)[/quote]
@BeerNutts: Ahh so looking at the third output above I am trying to call the render loop and something there is prohibiting me from continuing to call it more than 60/61fps.
Dont I want to keep V-Sync on though? Can anyone have a look at the movement code because I want to make sure that an object moves the same amount on a 100hz computer just as a 60hz one. Maybe I can just rely on this (seems like) 'automatic' feature...!
I have included to files which are the output of the framerate calc. the first is windowed the second is fullscreen. Notice the windowed one keeps going back to 60fps.[/quote]
Vertical synchronization is meaningful only in fullscreen mode. This is your problem.

Dont I want to keep V-Sync on though? Can anyone have a look at the movement code because I want to make sure that an object moves the same amount on a 100hz computer just as a 60hz one. Maybe I can just rely on this (seems like) 'automatic' feature...![/quote]
Nuh-uh. VSync can be overriden through the graphic driver's control panel, so you cannot rely on it being active even if you explicitly ask for it. And as you can see, it cannot be used in windowed mode. If you want to ensure the game runs at the same perceived speed regardless of framerate you need to use other methods, usually taking into account the elapsed time between two frames (there was this article that might come in handy though it's more about physics).

“If I understand the standard right it is legal and safe to do this but the resulting value could be anything.”

oh and this...

FULLSCREEN 80fps (m_pD3DDevice->Present(NULL, NULL, NULL, NULL); COMMENTED OUT):

second = 0 fps = 0 delta (ms) = 0 iFrameCycles = 0
second = 1 fps = 80 delta (ms) = 126 iFrameCycles = 186147
second = 2 fps = 80 delta (ms) = 2 iFrameCycles = 239753
second = 3 fps = 80 delta (ms) = 18 iFrameCycles = 237041
second = 4 fps = 80 delta (ms) = 17 iFrameCycles = 236471
second = 5 fps = 80 delta (ms) = 17 iFrameCycles = 240157
second = 6 fps = 80 delta (ms) = 17 iFrameCycles = 237241
second = 7 fps = 80 delta (ms) = 17 iFrameCycles = 235768
second = 8 fps = 80 delta (ms) = 18 iFrameCycles = 234334
second = 9 fps = 80 delta (ms) = 17 iFrameCycles = 237221
second = 10 fps = 80 delta (ms) = 17 iFrameCycles = 237300


so my code does really work but with present commented out. So how do I find out which V-Sync/s I need???

This topic is closed to new replies.

Advertisement