High Resolution Callback Timer (microseconds)

M

Michael Evans

First, we rely on a stable update rate so that our physics and dynamics
calculations and integrations are based on a known interval and
therefore are true-to-life.

Second, the graphics positions in our image generators are updated by
this dynamics application, and we need to update them at the rate they
are being refreshed so that we don't get any stutter from frames being
used twice or having to be thrown out.

Without microsecond timing resolution in some form, it is impossible to
get even close to the desired update rate. For example, 60 Hz would
require a frame interval of 0.016666 seconds, but with only millisecond
resolution, you can only time either 0.016 or 0.017 seconds. These
intervals give you either 62.50 Hz or 58.82 Hz.

We are familiar with the concept of using a hardware device to generate
a high resolution interrupt to trigger an ISR that runs our application
frame. But we are looking for a software alternative so that we don't
need extra hardware in the machine just for that purpose.

We have also tried using the millisecond timer rounded down to the
nearest whole millisecond, and then spinning in a while loop until the
remainder of the interval has elapsed, but this causes CPU usage to at
least double.
 
W

William DePalo [MVP VC++]

Michael Evans said:
We are familiar with the concept of using a hardware device to generate
a high resolution interrupt to trigger an ISR that runs our application
frame. But we are looking for a software alternative so that we don't
need extra hardware in the machine just for that purpose.

And I'd like a Ferrari for about 30 grand. :)

Seriously, Windows is a great operating system for many purposes but it is
not real time o/s. It will never make hard guarantees as to the latency that
you require.

You might want to look to third-parties such as this one:

http://www.vci.com/products/windows_embedded/rtx.asp

about which I have no first-hand knowledge.

Regards,
Will
 
T

Tom Widmer

Michael said:
First, we rely on a stable update rate so that our physics and dynamics
calculations and integrations are based on a known interval and
therefore are true-to-life.

Second, the graphics positions in our image generators are updated by
this dynamics application, and we need to update them at the rate they
are being refreshed so that we don't get any stutter from frames being
used twice or having to be thrown out.

Ahh, so AFAICT you don't need the software to be woken up with
microsecond accuracy at all! Instead:

1. You need to know accurately when the next frame will be displayed.
2. You need to be "woken" in plenty of time to get the physics and
display calculations done in time for the next frame (using the time of
that frame for the calculations).
3. When you have finished the calculations, you need to be able to
schedule the frame for the next vblank, and then go back to sleep until
you need to do the next frame.

That is a much easier task, and one I've done something similar to
before on Windows.
Without microsecond timing resolution in some form, it is impossible to
get even close to the desired update rate.

Why do you think that?

For example, 60 Hz would
require a frame interval of 0.016666 seconds, but with only millisecond
resolution, you can only time either 0.016 or 0.017 seconds. These
intervals give you either 62.50 Hz or 58.82 Hz.

Yes, but you don't have to wake up every 16ms, instead you can wake up
approximately when you need to do the work for the next frame, and also
sometimes when the vblank occurs, so that you can record the exact time
of that vblank. I think you should use the multimedia timer with one
shot timers and Events.

Here's my overall suggestion, which uses a single thread, but can be
made multithreaded if required.

At start, lets say there is >10 ms until the next frame update, and we
know when the last vblank occurred, since we polled the raster status
until we were in the vblank. Set the thread priority to max, at least
during the sleep and poll bits. Also consider boosting process priority
to max while sleeping and polling (but not while calculating physics and
graphics I think).

Then:

1. Calculate microsecond expected time of next frame (ETNF) based on
time of last frame and display frequency.
2. Do physics based on ETNF.
3. Update graphics based on physics.
4. Request display update at next frame with new graphics (e.g. use
DirectX with vsync enabled).
5. Schedule a wakeup for just before the next vblank (e.g. 1-2ms before
ETNF).
6. Get woken up.
7. If vblank hasn't happened, poll until it does happen. Record exact
time of vblank as actual frame time (ATF) in microseconds.
8. If vblank has been missed due to poor scheduling (this is Windows,
after all), just use the ETNF as the ATF.
9. Go back to 1.

8 might be hit quite often, but hopefully 7 will be hit often enough to
prevent any noticeable drift between your ETNF estimates and the ATFs.

Optionally, you can reduce CPU usage by only attempting to poll for the
vblank once every few frames. It's annoying that DirectX can't tell you
the time of the last frame, since surely it has access to this info.
That would remove the need for any kind of polling.
We are familiar with the concept of using a hardware device to generate
a high resolution interrupt to trigger an ISR that runs our application
frame. But we are looking for a software alternative so that we don't
need extra hardware in the machine just for that purpose.

Hopefully you won't need the hardware. However, even with the hardware,
there is a possibility of skipping the odd frame, since Windows has an
unbounded maximum response time.
We have also tried using the millisecond timer rounded down to the
nearest whole millisecond, and then spinning in a while loop until the
remainder of the interval has elapsed, but this causes CPU usage to at
least double.

You're going to have to explain why you have to *do* the calculations at
a particular time, as opposed to *using* a particular time for the
calculations.

N.B. This would all work better on a realtime OS like QNX or Lynx, which
don't have the concept of a late wakeup (if you schedule it for the
thread with the highest priority, it will happen as scheduled, to the
resolution of the kernel timer tick).

I hope that helps.

Tom
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top