开发者

frame rate on the iphone using mach_absolute_time

I have the following code, and wanted to get other set of eyes to make sure I have written the right code to calculate the frame rate of a scene. Could you please chime in?

This is written for the iPad using SDK 3.2.

thanks!

- (void)drawView:(id)sender
{
 mach_timebase_info_data_t timer;

 mach_timebase_info(&timer);
 uint64_t t1 = mach_absolute_time();

    [renderer render];

开发者_StackOverflow uint64_t delta = mach_absolute_time() - t1;
 delta *= timer.numer;
 delta /= timer.denom;

 NSLog(@"%lld ms: %.2f FPS", delta, 1000000000.0f/delta);
}


In case you want to measure the time spent rendering OpenGL, this won't work. OpenGL operations are processed in parallel and will not affect timing on the CPU. You can profile the time it takes to issue the OpenGL calls, but you won't be able to see how long it took them to finish.

This is unfortunate, but it makes sense. This is probably the reason why everyone's just eying their framerate: if the GPU can't finish processing in time, your CPU gets blocked and your timer (most likely CADisplayLink) will not fire "in time".

You may want to look into (expensive) profiling tools like gDEBugger, but I'm not sure they work on iOS.


I use CFAbsoluteTime to compute the frame duration in an openGL app. I stopped using mach_time because the results were not reliable.

- (void)update {

    // Compute Frame Duration
    static CFAbsoluteTime sPreviousTime = 0;
    const CFAbsoluteTime newTime = CFAbsoluteTimeGetCurrent();
    const CFAbsoluteTime deltaTime = newTime - sPreviousTime;
    sPreviousTime = newTime;
    float frameDuration = deltaTime;
    // keep frameDuration in [0.01 ; 0.5] seconds
    if (frameDuration > 0.5f) {
        frameDuration = 0.5f;
    } else if (frameDuration < 0.01f) {
        frameDuration = 0.01f;
    }

    [self tick:frameDuration]; // use frameDuration to do something every frame

}


Short answer : yes what you are doing is correct.

Longer answer : to get the time in seconds for a delta between two mach_absolute_time calls, you need to do the following:

// I do this once at launch.
mach_timebase_info_data_t timer;
mach_timebase_info( &timer );

// Start time.
uint64_t t1 = mach_absolute_time( );

// Do activity.

// End time.
uint64_t t2 = mach_absolute_time( );

// Calculate delta.
uint64_t delta = t2 - t1;

// Use denom/numer from timer.
delta *= timer.numer;
delta /= timer.denom;

// Convert nanoseconds to seconds.
float secondsElapsed = ( float )( delta / 1000000000.0 );

Of course, if you want a FPS, from you need the inverse of the seconds:

1.0f / secondsElapsed;

In your case, instead of doing:

float secondsElapsed = ( float )( delta / 1000000000.0 );

You are doing:

float inverseSecondsElapsed = ( float )( 1000000000.0 / delta );

So you do indeed get the FPS as intended, so all should work as intended.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜