Accurate timer events w/ no window available.

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Jason C

    #1

    Accurate timer events w/ no window available.

    Using C++, platform is Windows XP SP3.

    I have a multimedia application that runs a rendering loop that must
    be throttled to 60 iterations / second max. Currently it is
    implemented using a dirty and inconsistent wait loop, which I've
    included below. I am looking for a better way to implement frame rate
    throttling, and am looking for a timed event that meets the following
    requirements:

    * Does not require a window handle.
    * Does not require a message processing loop.
    * Minimum CPU usage is very important.
    * Consistent, accurate to within 0.1 ms would be ideal.
    * If loop time is greater than 1/60th of a second, it must still run
    the loop as fast as possible rather than skipping timeslices (e.g. run
    at 50fps instead of halving it to 30 with a lot of idle time).

    The SetTimer interface requires a message processing loop, and is not
    appropriate for this application. It also has dubious accuracy. I have
    just recently discovered the MSHTML Timer API (http://
    msdn.microsoft. com/en-us/library/aa741307(VS.
    85).aspx#The_MS HTML_Timer_API) , but have not tried using it yet.
    However, it appears that that also required a window handle to be
    available, but maybe I'm wrong?

    Current implementation, does not meet accuracy / consistency
    requirements in certain situations. The idea is to use the performance
    counter and wait in a loop, but use Sleep() with various parameters to
    minimize CPU usage (it is expected that Sleep(1) takes significantly
    longer than 1 ms), depending on the amount of time left to spare:

    // vars used below, for context
    LARGE_INTEGER tn; // this is the current time
    LARGE_INTEGER tl; // time of last frame
    LARGE_INTEGER tfreq; // performance counter frequency
    double tminftime; // 1.0 / max frame rate (in this case,
    1.0/60.0=0.016)

    // initial values of vars used below
    tminftime = 1.0 / 60.0;
    QueryPerformanc eFrequency(&tfr eq);
    QueryPerformanc eCounter(&tl);

    while (...) {
    renderFrame();


    // throttle frame rate; pause for remainder of 1/60th
    second time slice
    while (true) {
    QueryPerformanc eCounter(&tn);
    double realdt = (double)(tn.Qua dPart - tl.QuadPart) /
    (double)tfreq.Q uadPart;
    // if we're throttling frame rate and not enough time
    has passed, wait.
    if (realdt < tminftime) {
    double timeleft = tminftime - realdt;
    if (timeleft 0.011) // if there's plenty of time
    left...
    Sleep(1); // ... be really nice
    else if (timeleft 0.001) // if we're getting
    closer...
    Sleep(0); // ... be kind of nice
    // and if < 1 ms remaining then don't
    be nice at all.
    } else {
    break;
    }
    }
    tl = tn;


    }

    Thanks,
    Jason
Working...