Render Loop probs...

Started by
9 comments, last by devronious 16 years, 11 months ago
I was given the following render loop idea from a gentleman and it works super. The framerate is up as fast as you so desire to as low as you want. Only prob is that it seems to eat up all the cpu load. Even when I drop it from >1,000 fps down to 40fps. Perhaps I should be putting the system into an idle mode somehow during the wait for the next frame? Anyways, I need to figure out a Managed DirectX one that doesn't eat up all the cpu load, or at least I can tell it to and not to at different times. Thanks for any help on the matter.


    static class Program
    {

        private static int interval = 10;

        private static int lastRender = Environment.TickCount;

        static void Main()
        {
            Settings set = new Settings();
            DialogResult res = set.ShowDialog();
            if (res == DialogResult.OK)
            {
                SceneForm form = new SceneForm(set.DisplayMode, set.Windowed);
                form.Show();
                while (form.Created)
                {
                    if (Environment.TickCount - Program.lastRender > Program.interval)
                    {
                        form.Render();
                        Program.lastRender = Environment.TickCount;
                    }
                    Application.DoEvents(); //Let the OS handle what it needs to
                }
                Application.Exit();
            }
        }
    }


Advertisement
That's actually not the most efficient renderloop around. I would suggest you go with Tom Miller's renderloop code..

https://blogs.msdn.com/tmiller/archive/2005/05/05/415008.aspx

To free up CPU time add a Thread.Sleep() call in your renderloop, like so..

private void OnApplicationIdle(object sender, EventArgs e){    while (AppStillIdle)    {         // Render a frame during idle time (no messages are waiting)         UpdateEnvironment();         Render3DEnvironment();         System.Threading.Thread.Sleep(10); // sleep a bit to free up some CPU time    }}


You can of course change the sleep amount to whatever you like.
Sleep()ing during a frame is usually a very good way to completely ruin performance. You shouldn't be sleeping if your application has work to do, which it does when you're rendering.

If you want your application not to use up 100% cpu when it isn't active, just replace the rendering with a sleep while it is inactive. When your app is active, it is natural for it to take up all resources availble to it (assuming you're making a game or similar interactive application).
Sirob Yes.» - status: Work-O-Rama.
sirob,

Thanks, that makes sense and satisfies my concerns about cpu usage. I guess it means that my program is probably doing good since it is rendering 1,000+ fps while at 100% cpu load and +5,200 polys?

Headkaze,

Had some trouble running Tom's code. It seems perhaps some refs or other portions are missing from that snippet. Had trouble finding the following types:

NativeMethods
WindowMessage
Quote:Original post by devronious
I guess it means that my program is probably doing good since it is rendering 1,000+ fps while at 100% cpu load and +5,200 polys?

That means absolutely nothing.

Quote:Original post by devronious
Had some trouble running Tom's code. It seems perhaps some refs or other portions are missing from that snippet. Had trouble finding the following types:

NativeMethods
WindowMessage

WindowMessage is simply called Message (and I think it's in System.Windows.Forms). NativeMethods isn't built-in, IIRC, and simply includes a PInvoke to PeekMessage.

Here's my working code:
	// In the constructor:        System.Windows.Forms.Application.Idle += new EventHandler(OnApplicationIdle);        private void OnApplicationIdle(object sender, EventArgs e)        {            while (AppStillIdle)            {		if (Device == null)			// Init Device		// Frame	    }	}        private bool AppStillIdle        {            get            {                Message msg;                return !PeekMessage(out msg, IntPtr.Zero, 0, 0, 0);            }        }        [System.Security.SuppressUnmanagedCodeSecurity]        [DllImport("user32.dll")]        public static extern bool PeekMessage(out Message msg, IntPtr hWnd, uint messageFilterMin, uint messageFilterMax, uint flags);


As for which loop to choose, the OnApplicationIdle loop is superior, but it shouldn't really make a difference. Go with what you prefer.
Sirob Yes.» - status: Work-O-Rama.
Render loops and CPU usage seems to be quite topical on here lately. An interesting thread with more opinions can be found at http://www.gamedev.net/community/forums/topic.asp?topic_id=445787

Personally I like to use Sleep() to keep the CPU usage down. A laptop for instance will use more battery with a CPU running at 100%. For my purposes I need to share the CPU with other apps, so it makes sense for me to use it.
Headkaze,

Thanks for the post resource.

Sirob,

Quote:That means absolutely nothing.


Are you refering to the affect that hardware configurations will have on performance? Are perhaps there's another reason it means nothing?
Original post by Headkaze
Render loops and CPU usage seems to be quite topical on here lately. An interesting thread with more opinions can be found at http://www.gamedev.net/community/forums/topic.asp?topic_id=445787

Personally I like to use Sleep() to keep the CPU usage down. A laptop for instance will use more battery with a CPU running at 100%.


Quote:For my purposes I need to share the CPU with other apps, so it makes sense for me to use it.

because Windows doesn't have a scheduler, so you need to do it manually...
</sarcasm>

Every OS made in the last 12 years is quite capable of multitasking. Which means it will *all by itself* make sure all running processes get CPU time. If your app manages to use 100% it is *not* because it's greedy and starving out other processes. It's because Windows has no one else to give the CPU time to. Most processes use hardly any CPU, which means Windows generally ends up putting 99% of the CPU time into the idle loop. If there's an app running that's willing to soak up all the CPU time it can get? Well, then Windows can give it those 99% that would otherwise have been wasted. That does *not* mean other processes are missing out or getting starved. It simply means they pick the few microseconds they need, and then leave the rest to whoever wants it. Which means your app.

So, using 99% CPU is generally not a bad thing, even if you expect the user to have other apps running in the background, because it'll only ever be allowed to eat 99% CPU if there's nothing else that needs CPU time.

The best rule of thumb is quite simple. Use as much CPU time as you need, and no more.
If you're trying to make a game that runs smoothly, then for heavens sake, *don't* force the CPU to go into idle mode in the middle of a frame. Instead, spend the CPU time you need to get the job done, and let Windows worry about how much time it'll give you, and how much will go to other apps.

And of course, if you don't need all the CPU time (say, if you're running with a fixed framerate, for example, or if you're writing a word processor or a mp3 player or anything else that only needs a small amount of CPU time every now and then), then yes, you should definitely call Sleep() to make sure Windows can give all the CPU time to other processes. But don't do it every frame *just because you feel sorry for the other processes*. Windows take care of that, and it does so much better than you.

Of course, if you're trying to conserve power, then yes, Sleep()'ing might be a good idea too. Although even then, I'd test it to see if it even makes a noticeable difference on battery life (doesn't almost everyone who play games on their laptops do it while it's plugged in anyway? Don't know many people who do it on battery)
Quote:Original post by devronious
Quote:That means absolutely nothing.

Are you refering to the affect that hardware configurations will have on performance? Are perhaps there's another reason it means nothing?

It means nothing since it provides absolutely no reference to what you are doing, or which hardware you're on. Furthermore, there's nothing to say the performance of this chunk of code will have any effect at all at the final code you use. If, for example, your application is limited by some other bottleneck, say, a GPU limitation, the performance of the renderloop will have little to no effect on overall performance.

There's no point in improving performance in the sections of code that don't limit your application's running speed. In most cases, 90% of the time is spent on executing 10% of the code. Before you start making changes, make sure you identify that 10% of code. Otherwise, everything you do will have no effect, overall.

Hope this helps.
Sirob Yes.» - status: Work-O-Rama.
I myself am using SleepEx() to limit the rendering framerate to 100 FPS, for instance. Although I've read on these forums that it's limited to 10 ms precision, this is not mentioned on Platform SDK. Apparently I could limit my target FPS to about 300 (3 ms interval) and it ran pretty reliably, as well as on the two seperatare machines I've tried. Maybe it's luck, but I'd say it works just fine and no, you don't need to render at 1000 FPS and use 100% of CPU all the time. [wink] Just take what you need (e.g. our game needs at least 60 FPS to have maximum response) and leave the rest to the system to have some rest and cool down. [smile] After all, the hotter your system runs, the less time it will last.

This topic is closed to new replies.

Advertisement