Alternative to NSTimer - Printable Version
+- iDevGames Forums (http://www.idevgames.com/forums)
+-- Forum: Development Zone (/forum-3.html)
+--- Forum: iPhone, iPad & iPod Game Development (/forum-11.html)
+--- Thread: Alternative to NSTimer (/thread-1592.html)
Alternative to NSTimer - warmi - May 20, 2009 08:17 PM
DoG Wrote:Not sure where that is coming from, but that statement isn't universally valid, and most certainly you can get much finer granularity from a timer, depending on the environmental factors.
A custom loop is a better choice ... it is dead easy to code and having another thread just for handling timing is a waste.
After all, your game is driven by its own update loop and thus you can get just about perfect timing ( if you are done ahead of time , simply forward any further processing to the default loop for whatever amount of time you have left. )
Alternative to NSTimer - arekkusu - May 20, 2009 09:05 PM
Folks who find NSTimer insufficient should file a feature request for a better API.
For example, if want to know when the screen refresh happened so that you can redraw your scene, you should ask for API that lets you register for notification of screen refreshes. That way you're responding to a real hardware event, not some arbitrary timer that has no relation to anything.
Alternative to NSTimer - AnotherJake - May 20, 2009 09:43 PM
arekkusu Wrote:Folks who find NSTimer insufficient should file a feature request for a better API.
It's a mystery. In all the years OS X has been around now, Apple has apparently shown no interest in providing a hardware generated VBL callback (irq, or whatever). I gave up complaining about it years ago. Glad to see there is a new breed of whiners in this thread to take my place!
That said, there is a lot of [mis]information in this thread. Folks would be wise to read DoG's posts a little more carefully.
 I meant to say *mis*information, but had a Freudian slip and said *dis*information originally because it seems to me there is a bit of misinformed bias from a few angles.
Alternative to NSTimer - warmi - May 20, 2009 10:27 PM
arekkusu Wrote:Folks who find NSTimer insufficient should file a feature request for a better API.
Uhh .... that's generally handled by eglSwapBuffers which unfortunately is not available because we are not really rendering to a framebuffer but to what is essentially a texture ( which then gets composited with other system layers)
Incidentally, that's the reason (I suspect) why there is no anti-aliasing available for OpenGL ES apps on the iphone.
While the GPU is perfectly happy to anti-alias when rendering to a framebuffer, it doesn't support it for rtt renders.
Alternative to NSTimer - maximile - May 21, 2009 05:46 AM
AnotherJake Wrote:In all the years OS X has been around now, Apple has apparently shown no interest in providing a hardware generated VBL callback (irq, or whatever).
Weren't Core Video display links were meant to sort that? (No use for iPhone)
Alternative to NSTimer - arekkusu - May 21, 2009 05:47 AM
warmi Wrote:that's generally handled by eglSwapBuffers
It certainly is not.
Swap (whatever the API flavor) presents your framebuffer so you can see it. This action may interact with hardware beam sync or a window compositor, and therefore have timing implications.
But, the Swap itself has nothing to do with telling you when to draw.
Alternative to NSTimer - warmi - May 21, 2009 07:32 AM
arekkusu Wrote:It certainly is not.
Yeah, but if you are drawing to a backbuffer then it doesn't matter when you draw - what matters is if your swap is synchronized.
Alternative to NSTimer - AnotherJake - May 21, 2009 07:35 AM
maximile Wrote:Weren't Core Video display links were meant to sort that? (No use for iPhone)
Display links are just high priority timers. Yes, the purpose is to be better than regular timers for graphics purposes. I've tested my stuff extensively with display links and found zero improvement in timing over a simple over-revved 1k timer on the Mac (i.e, they don't eliminate beat frequencies between the drawing code and the display refresh). Over-revved timers don't help on iPhone, and can actually make performance worse if they're too high a frequency.
Alternative to NSTimer - arekkusu - May 21, 2009 09:24 AM
warmi Wrote:Yeah, but if you are drawing to a backbuffer then it doesn't matter when you draw.
It matters if you're going to draw more than one frame.
Everyone on this forum is writing games, and games generally draw more than one frame, with the goal of producing smooth animation.
The definition of "smooth animation" is: one frame drawn per display refresh.
The problem with implementing that is that you need to know what the display refresh rate is, and when the display refresh starts. The naiive implementation of using an NSTimer at 60.0 Hz doesn't work, because "60.0" is an arbitrary number with no correlation to either the hardware refresh rate or refresh start time.
As discussed in this thread, overdriving the timer can work (if your drawing thread blocks on sync, which is true on Mac OS X) but that's really an abuse of the system to request more notification than you need.
What you really need to have is a notification when the hardware has just refreshed the display. Every game console has this. Even Apple used to have it.
Alternative to NSTimer - warmi - May 21, 2009 09:43 AM
arekkusu Wrote:If matters if you're going to draw more than one frame.
We are talking about two different things ... you are talking about animations driven (or synchronized ) to a fixed refresh rate (something quite common on consoles) and I am talking about the opposite .. using synchronized swap just to avoid tearing and related issues ... while keeping the animation rate based on a system timer ( basically variable rate).
Alternative to NSTimer - arekkusu - May 21, 2009 09:58 AM
Fair enough. If you want a system timer at an arbitrary rate, NSTimer is great for that.
That's not generally a good way to drive rendering, was my point.
Alternative to NSTimer - warmi - May 21, 2009 10:19 AM
arekkusu Wrote:Fair enough. If you want a system timer at an arbitrary rate, NSTimer is great for that.
Not arbitrary but rather relatively predictable ... something NSTimer is not good for.
Yeah, it would be perfect if you could code for the iPhone the way people code on consoles ... assume a fixed frame rate and be done with it.
The iPhone already has two hardware profiles out there not to mention unrelated background processes which you cannot control, so in this regard is more like a PC than a console.
Alternative to NSTimer - DoG - May 22, 2009 01:39 AM
warmi Wrote:Not arbitrary but rather relatively predictable ... something NSTimer is not good for.
The iPhone/Mac OS is a preemptive multitasking system. Whatever you do in your little custom loop won't change that fact. A custom loop will not have any measurable advantage over a plain runloop with a single NSTimer on the *same thread* as the custom loop.
I also neglected to mention that if you set your NSTimer to a really small interval, but your buffer swap blocks the thread anyway, it's probably as efficient as it gets, as your timer will fire once per frame, as soon as the scheduler permits.
Anyhow, as for the screen-synced timer, that is also a bit difficult to handle. As threads are preemptive, the OS doesn't guarantee any execution time limits. Thus, even if your callback was called at the exactly right time, you could still miss the next screen refresh, if your thread didn't get enough CPU time. Temporal aliasing is unavoidable to some degree if the CPU load is high, which with a game, it typically is. Even if the amount of computation per game frame is constant, the execution time may still vary wildly. Incidentally, if you only measure time once per frame, you don't know if the culprit is that the timing is off, or that execution is taking too long. **
On a desktop Mac, input processing probably takes an order of magnitude less time to execute, due to the faster processor, etc, than on the iPhone. So if input processing on the phone takes 30% CPU time, it probably takes 3% on the desktop, and so produces much less noticable jitter, all else being constant. Also, with multiple cores, contention is even less of a problem, and even with a high load, the scheduling latency is greatly reduced.
If you had control of the thread scheduler, and a hardware interrupt for screen sync, and bounded execution time, you could probably reduce jitter a bit. However, if the amount of CPU time you use is variable, and sometimes more than what you got per screen refresh, you'll have to accept some amount of temporal aliasing.
(** if your buffer swap is synced, it'll always seem as if NSTimer skips firing some frames, eg you'll have 0.033, 0.033, 0.066, 0.033 as frame time intervals. But that isn't the fault of NSTimer, as your thread could have been blocked for 0.032s of that 0.066, simply because the buffer swap was initiated a fraction too late, and the timer can only fire after it has been completed. A custom game loop will show the exact same symptoms.)
Alternative to NSTimer - warmi - May 22, 2009 09:14 AM
DoG Wrote:The iPhone/Mac OS is a preemptive multitasking system. Whatever you do in your little custom loop won't change that fact. A custom loop will not have any measurable advantage over a plain runloop with a single NSTimer on the *same thread* as the custom loop.
Of course I won't get real-time response .. I know that.
All I am saying is that I got more stable timing using my own loop rather than NSTimer ... especially when dealing with heavy input event loads.
I guess I could go with setting NSTimer to fire as fast as possible but then , if my my game loop actually is running below 60 MHZ, I will end up synchronizing running at 60 FPS, which may or may not be the best option.
It comes down to the fact that I can't control the swap interval parameter on the iPhone.
Alternative to NSTimer - demonpants - Jun 8, 2009 02:41 PM
Just to add to this:
If you're doing your own loop like this, new versions of the iPhone OS beyond 2.2.1 will hang on startup, unless you use:
In order to launch into the loop. If you simply say [self mainLoop] the app will never start up in new OS versions. In old versions, this was allowed, but it must be avoided in new ones.
Hopefully that will help.