FPS Limiting

Started by
8 comments, last by Thunder_Hawk 21 years, 2 months ago

    
void LimitFPS (DWORD fps)
{
	static DWORD dwFpsTimerCount = 0;
	static DWORD fun = 0;		// Used for evener...a very pseudo-random number :)

	fun++;				// If number overflows, it goes back to zero, so what? ¦*þ

	DWORD evener = (1000%fps && !(fun%int(10/(double(1000%fps)/double(fps)))/10))? 1 : 0;
	/* Use lazy evaluater to protect against division by zero.  Expression uses a predictably
	random number to ensure the fps is accurate...fixes the accuracy problem introduced by
	the integer while loop below. */
	DWORD count = 1000/fps + evener;
	if( dwFpsTimerCount != 0 )
		while(timeGetTime() < (dwFpsTimerCount + count) );
	dwFpsTimerCount = timeGetTime();
}
    
Does anyone know an easy way I can give up the wasted time there to other (hungry) programs? ______________________________ And the Phoenix shall rise from the ashes... --Thunder_Hawk -- ¦þ ______________________________ [edited by - Thunder_Hawk on February 9, 2003 9:22:33 PM]
______________________________________________________________________________________The Phoenix shall arise from the ashes... ThunderHawk -- ¦þ"So. Any n00bs need some pointers? I have a std::vector<n00b*> right here..." - ZahlmanMySite | Forum FAQ | File Formats______________________________________________________________________________________
Advertisement
You could use sleep,

but in unix threads(or should I say posix) there is a function called yield() which tells the OS : "I have some free time, so give it to other processes". The advantage of that over sleep is that if no other processes need the power, it will give it back to you, so you have less time imprecision than with sleep.

I have never done threading in windows, so I don''t know if there is something like yield, but I assume there is.
You _could_ use Sleep(0), your program then uses 100% of the processor but whenever another application wants some CPU time it will free the necessary CPU time for it.
But in the end your processor will still run at 100%.

Using Sleep() is not entirely precise and the time specified for the application to sleep can fluctuate within a 10ms resolution, so if you want exact results Sleep() is not the way to go.
quote:Original post by EinVante
You _could_ use Sleep(0), your program then uses 100% of the processor but whenever another application wants some CPU time it will free the necessary CPU time for it.

erm, no. calling sleep suspends your execution for the specified duration, which means that calling thread will not use any cpu time.
Hmm...I''ve tried this out and I noticed the accuracy isn''t very nice, is there any more accurate solution?
______________________________________________________________________________________The Phoenix shall arise from the ashes... ThunderHawk -- ¦þ"So. Any n00bs need some pointers? I have a std::vector<n00b*> right here..." - ZahlmanMySite | Forum FAQ | File Formats______________________________________________________________________________________
As far as I know, no. However, I built a function called Rest that takes the desired maximum amount of CPU power and calls Sleep every few frames, the net result being that you have a little more control over your usage. I''ve tried running it under full load, and it''s accurate within +-2% on average.

I got the idea from SHilbert, but my implementation uses a static local timer object that packages things up. I''m not posting code here because it''s too implementation specific, but if you want to do something similar, the description I''ve given should be sufficient.

//email me.//zealouselixir software.//msdn.//n00biez.//
miscellaneous links

[twitter]warrenm[/twitter]

ZE: I tried something similar to your idea and it turned out very "jumpy" (a very disturbing effect) and not much more accurate... I think I''ll just resort to sleep when doing text or something more static...
______________________________________________________________________________________The Phoenix shall arise from the ashes... ThunderHawk -- ¦þ"So. Any n00bs need some pointers? I have a std::vector<n00b*> right here..." - ZahlmanMySite | Forum FAQ | File Formats______________________________________________________________________________________
Clearly you did something wrong, because this code works beautifully:
void CGame::Rest(float TimePercent){	float TimePerSec = 1000*(1-TimePercent);	static CTimer SleepTimer;	static float Accum = 0;  	Accum += SleepTimer.GetLastFrameTime()*TimePerSec;  	if(Accum >= 10)	{		Sleep(int(Accum));		Accum -= int(Accum);	}  	SleepTimer.Update();} 

Later,
ZE.

//email me.//zealouselixir software.//msdn.//n00biez.//
miscellaneous links

[twitter]warrenm[/twitter]

ZE: As usual you were right. Although, I wouldn't say that code is overly implementation dependant (it's written clear as a bell). The inaccuracy I reported was due to me sticking with the "evener" setup instead of using a float straight out. However, I believe the "jumpiness" is inherant to the structure of the code. It seems my eye can distinguish between the sleeping frames and the no stop frames. Increasing the interval has proven to stop it from being noticable though. Here's my new code:


    void LimitFPS (float fps){	if (fps <= 0) return;   // Obvious error	static DWORD dwFpsTimerCount = 0;	static float total = 0;	DWORD dMilliseconds;	if (dwFpsTimerCount) {		dMilliseconds = timeGetTime() - dwFpsTimerCount;	} else {		dMilliseconds = 0;	}	total += 1000/fps - dMilliseconds;	if (total >= 3) {		Sleep (int(total));		total -= int(total);	}	dwFpsTimerCount = timeGetTime();}    


This code seems just as accurate as my old code (usu. within 0.1 of the desired fps).

______________________________

And the Phoenix shall rise from the ashes...

--Thunder_Hawk -- ¦þ
______________________________

[edited by - Thunder_Hawk on February 10, 2003 8:38:28 PM]
______________________________________________________________________________________The Phoenix shall arise from the ashes... ThunderHawk -- ¦þ"So. Any n00bs need some pointers? I have a std::vector<n00b*> right here..." - ZahlmanMySite | Forum FAQ | File Formats______________________________________________________________________________________
Fantastic! Glad to see you got it working

(BTW, I''m not usually right; I just make sure I delete my disinformation or refute to the point where no one knows what the facts are )

Peace,
ZE.

//email me.//zealouselixir software.//msdn.//n00biez.//
miscellaneous links

[twitter]warrenm[/twitter]

This topic is closed to new replies.

Advertisement