Does CADisplayLink automatically control the app's timestep?

I'm writing an iOS game that uses OpenGL ES 2.0. I have my 'OpenGLView' which contains a

- (void)setupDisplayLink {
CADisplayLink* displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(render:)];
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}


And then my

- (void)render:(CADisplayLink*)displayLink {


function which at the end of the processing calls

[_context presentRenderbuffer:GL_RENDERBUFFER];


Like most people I've found the http://gafferongames.com/game-physics/fix-your-timestep/ tutorial but I've been thinking.

With a CADisplayLink, has the framerate limiting been done for me already by iOS, meaning I don't need to calculate the timing of each frame?

Also, as a sanity check, the 'render' function is where all my game logic goes? I'm currently treating it as the equivalent of a

while (!quit) {
do_stuff();
render();
}


loop you see in traditional game loop designs, or is this only for rendering?

1 Answer

A CADisplayLink does indeed do framerate limiting. Under normal operation, you will never get -render: messages any faster than the display's refresh rate.

I'm not sure what the standard practice for doing game logic in -render: is, but I can tell you two things: one, CADisplayLink was not designed to run both your rendering and your game logic, and two, it's easier but less performant to let it handle both.

For example, if you overshoot a frame slightly once, CADisplayLink may wait for the next refresh before calling into your code, which would deprive you of useful time in which you could be updating your game state. But you also can't simply go into a standard "until-quit" game loop (at least on the main thread): your display link will not fire then.

The first thing I'd be tempted to try is a CADisplayLink that only does rendering, and a dispatch_async-driven update loop, where the game's update step dispatches another update step when it completes. In theory, that would allow -render: to happen if necessary, but immediately start another update step if not. If you want a fixed timestep, you may be able to use dispatch_after to force your next update frame to wait a certain duration.

I have no idea if the above is workable, unfortunately, this is merely the first thing I'd try.

• OK, that's good. I'll ask a separate question about the proper use of CADisplayLink. – Piku Feb 11 '12 at 12:21
• Here's a Stack Overflow thread that asks a very similar question. The dispatch source approach seems good: stackoverflow.com/questions/8552064/… – John Calsbeek Feb 11 '12 at 12:23