Released in june 2017, Apple's top of the line iPads come with ProMotion technology, or 120Hz display refresh. Here is how to support it in your game, and what it will bring.
First off, without actually running a 120Hz game on an iPad Pro, it is hard to convey what it brings. You can't show it in a video, so it has to be experienced in person. A game that runs at 120Hz feels incredibly smooth. Before I tried it, I expected the difference between 60fps and 120fps to be very small compared to the 60fps vs 30fps difference. But somehow it does bring it to a whole new level of smoothness. Combined with a touch display, it makes for a special experience.
So, how are we going to achieve this magical 120Hz refresh on the iPad Pro (2nd generation)? Let's start with the good news: the GPU in the iPad Pro is an absolute beast. Take the fastest mobile GPU you can think of, and then double that speed. That's how fast it is.
Provided you don't go crazy in your fragment shader, the GPU will be more than capable of cranking out 120 frames each second, at native resolution no less, and MSAA anti-aliased. And I found that it is even easy to achieve with OpenGL ES2 or OpenGL ES3, so there is no need to resort to Apple's Metal API.
Below is a screenshot of an Xcode performance measurement of one of my OpenGL ES2 apps. As you can see, it takes a mere 2.1ms to render a frame for a 10.5" iPad Pro. That is very comfortably within the available 8.33ms refresh cycle. We also see that the GPU spends more time fragment shading (RENDERER) than vertex shading (TILER) because of the high number of pixels on an iPad Pro.
Ok, let's assume we have the rendering covered. That's only half the story of course. We will only benefit from 120Hz refresh if we have something different to show each frame. This means that we need to step through our game's simulation in smaller steps. Twice as small, to be exact.
On this front, I was quite fortunate: Ever since my earliest iOS programming (which I started in 2009) I have ran my physics simulation at 120Hz, while rendering at 60Hz. So where I previously would step through the physics twice before rendering, I simply have to do one physics step (8.33ms) followed by rendering.
If your physics game used a 16.6ms delta-t step, then you need to cut that in half, and do two of those steps (or sometimes even more) on older devices, and just one for the iPad Pro.
For implementation, this is what I do each frame: I measure the elapsed time since last frame, and figure out which closest number of 8.33ms steps that corresponds to. And then step that many times. I've written an article before on getting the best time step for your game, but I'll just briefly describe how you could do this:
Note that if your game is multi platform and you would like to support intermediate display rates like 90Hz as well, then it's better to take even smaller timesteps, as outlined in the linked article.
Once your game can (1) render fast enough and (2) simulate fast enough, one thing remains to be done. We need to tell UIKit that we prefer 120Hz on devices that are capable of it. If you derive from Apple's GLKViewController, then this is how to approach this in code:
// We should be running as fast as we can. This means 120Hz on an iPad Pro. UIScreen* scn = [ UIScreen mainScreen ]; self.preferredFramesPerSecond = [ scn maximumFramesPerSecond ];
In case your app maintains its own CADisplayLink instead, just tell the Display Link to run at this rate, with:
UIScreen* scn = [ UIScreen mainScreen ]; displayLink.preferredFramesPerSecond = [ scn maximumFramesPerSecond ];
Which is pretty much the same: you check the maximum fps of the screen, and set it as preferred on either a Display Link or a GLK View Controller, and your set. Apple's documentation states that this is only a hint, and iOS is free to interpret it, in my experience, it always actually does 120Hz on the iPad Pro.
I've been updating my app store portfolio, and am pleased to report that three of my games now run buttery smooth on the iPad Pro:
The first title runs at 120Hz, always, never dropping a single frame. The third title does run 120Hz, but when the excavator or bulldozer starts ripping the ground, the simulation code gets strained, causing it to drop frames. So there are limits to this: if your sim code does crazy heavy computations, then even the latest iPad device will not help you there.
Did you update your iOS apps for 120Hz support? If so, what are your experiences? I love to read about them in the comments.