Q: Hey, I'm spending a lot of time spinning in the
graphics driver, waiting for a page flip, because I'm
v-synced. Wouldn't it be better to Sleep() away that time,
to give up some CPU to other applications?
A: That should work, with some caveats. I'm assuming Windows here (because
otherwise you'd be talking about usleep() :-)
What you're doing is trying to make a time-sharing consumer OS do what's
basically a real-time task. This isn't super easy, but can be done with some
Sleep()-ing is very jittery on DOS-based Windows. At best, you get
+/- 20 ms precision, which is too low to use for interactive applications that
want smooth frame rate. So detect Win98/ME and turn off sleeping, or have a
check-box to turn it off.
Sleep() signals to the OS that you have nothing better to do, which will cause
SpeedStep CPUs to slow down. Unfortunately, this means that your main loop will
run at the slower speed, so you'll be falling behind, and won't be sleeping.
Finally, the OS will notice you're not sleeping, and up the CPU speed. Then
you'll start sleeping again, and the OS turns on SpeedStep... Detect SpeedStep
and turn off sleeping, or have a check-box to turn it off.
Sleep() may wake up later than you tell it to (as I said, jitter), although
it's pretty good on NT-based Windows (such as Windows XP). Thus, I'd set a
wake-up point about 2 milliseconds before when I need to swap frames, and just
accept that I'll be spinning for 2 milliseconds each frame (minus wake-up
delay). If there's less than 2 ms left before flipping, don't sleep at all. You
may find that wake-up precision is better if you raise the priority class of
your application and the priority of your thread.
Sleep() does not wake up if there are windows events waiting for your window.
For better interactivity, you may want to create an event that you never set,
and then call MsgWaitForMultipleObjectsEx() with a time-out. This is known as an
"alertable" sleep, and will wake you up if there are suddenly events delivered
to your application (such as mouse movement). You could even run your Windows
message pump that way: sleep and/or handle messages until 2 milliseconds before it's
time to flip; then flip; then handle any remaining Windows messages before you
go on to simulate and render the next frame.