Choppy touch response on lower FPS - iphone

I'm making an iPhone game which has a quite intense use of pixel shaders. Some effects make my fps rate sometimes drop down to ~22 FPS in the 3GS, but it is around ~27 most of the time.
When the FPS rate is down there, the touch gesture response becomes extremely choppy. In other words, the gesture update time reaches nearly 5hz, which is much slower than the game itself.
Has anyone experienced similar problems? Is there any way around it?
Note1: I'm already using CADisplayLink
EDIT: I had a significant improvement by manually skipping even frames. I'm not sure if that is a good thing to do but the game remained quite playable and I'm sure it is using much less CPU now.

I have a similar situation in one of my applications, where I have very heavy shaders that can lead to slower rendering on older devices, but I still want to have the framerate be as fast as it can on more powerful hardware.
What I do is use a single GCD serial queue for all OpenGL ES rendering-related actions, combined with a dispatch semaphore. I use CADisplayLink to fire at 60 FPS, then within the callback I dispatch a block for the actual rendering action. I use a dispatch semaphore so that if the CADisplayLink tries to add another block to the rendering queue while one is running, that new block is dropped and never added.
I describe this approach in detail in this answer, and you can download the source code for my application which uses this here.
The GCD queue lets you move this rendering to a background thread, which leaves your interface responsive, while scaling the FPS so that your rendering runs as fast as your hardware supports. This has particular advantages on the new dual core iOS devices, because I noticed significant rendering speed increases just by performing my OpenGL ES updates on this background queue.
However, as I describe in that answer, you'll need to funnel all of your OpenGL ES updates through this queue to avoid the potential for more than one thread from simultaneously accessing an OpenGL ES context (which causes a crash).

If your app's game loop run at 22 fps, but is requesting 30 fps, that means that the app is oversubscribing the total number of CPU cycles available per second in the UI run loop. Either try putting more stuff in background threads, or turn your requested frame rate down to below what you can actually get (e.g. set it to 20 fps), so that there is more time left for UI stuff, such as touch event delivery.

Related

CADisplayLink accuracy issues with OpenGL ES on iOS

My iOS game is currently using CADisplayLink for timing of OpenGL rendering operations. I've got a GCD dispatch queue running on a second thread that issues all the OpenGL rendering and state calls to the GPU. Everything works fine, except the timing isn't perfect. I'm seeing frame skips and glitches on occasion, even when the animation interval is changed from 1 (60Hz) to 2 (30Hz).
CADisplayLink calls your selector from the RunLoop on the main thread, which means it can only fire in between other dispatched jobs and input events that the main thread is processing. (I've confirmed this is the case by logging these jobs/events). If those operations take several milliseconds, then CADisplayLink will never be perfectly accurate because it can't interrupt whatever is currently running on the main thread. As I imagine most games do, I'm running game simulation, physics, and scene culling on the main thread.
So what I'm thinking is that I should move all the game simulation and physics stuff off the main thread so that touch events and CADisplayLink can fire as close to when it should be as possible. But I'm not sure if this will solve anything and it's not a trivial amount of work.
I'm wondering, since the presentRenderBuffer call is really the thing that synchronizes your frame with the actual hardware display, maybe all I need is just a really accurate timer that can run in it's own thread (perhaps at higher priority) and trigger the rendering that way. Then I can keep everything on the main thread. It seems all CADisplayLink provides is a way to wait in the case when my code is running faster than 60Hz, so it seems to me that a similar kind of delay can be coded just as easily using a separate thread. What am I missing here?

Why is my touch event frequency slower on iOS 4.0?

I'm writing a finger sketch type app and had the app working great on iOS 3.0. However, running the app under iOS 4.0 or greater is causing problems. Specifically, I am receiving touch events to my app approximately 5x slower on the new OS than on the old. This obviously causes my app to draw poorly because I'm capturing 5x less data points to draw between.
Any ideas on how to speed up touch event frequency on iOS4?
Certain graphics operations take a lot longer in iOS4.x than in 3.x (somewhere between 2X to 10X slower). The longer graphics execution times could be blocking the main UI thread, and not leaving enough time for the main thread run loop to handle user (touch) events.
Profile your drawRect code and see if it's now taking longer that one refresh rate tick time. If so, try speeding up or breaking up your graphics renders, or try a lower frame rate, and see if any of that helps.
You should profile your code with Shark to see where the bottleneck is. What is probably happening is some of your code that executes on the main thread (most likely something that runs in response to a touch) is taking longer than expected which is preventing your app from receiving touch events
Block the main thread less.

iPhone + OpenGL + Touches: FPS drop

Recently I ran into a very strange issue: touching the screen of the iPhone and moving a finger around can eat up to 50% of my FPS. Yeah, I checked my code for possible bottlenecks – not the issue. The last resort I tried before writing this post – commenting out all the touch processing code and looking at FPS then. Results are: no touches – 58-60. Touching and moving the finger – 35-40 FPS instantly.
The rendering is done in a separate thread, so that no main runloop events shall collide with it. However, it's very crushial for me (and the game I develop) to resolve this issue, because such FPS drop is really noticeable.
Thank you for your help in advance.
UPDATE: seems that setting rendering thread's priority to higher value helps a bit...
The iPhone, iPod Touch, and iPad are all single-processor, single-core devices. Simply putting your rendering code on a separate thread from touch event handling—though a good idea—won't prevent the touch processing from eating up CPU cycles. The only way to make your framerates go up will be to either make the touch handling code faster or make the rendering faster. Which you pursue depends on the specifics of your application.

iPhone: how to prioritize items in a CFRunLoop (OpenGL related)

I have an OpenGL application which is rendering intensive and also fetches stuff over HTTP.
Following Apple's samples for OpenGL, I originally used NSTimer for my main painting loop, before finding out (like everyone else) that it really isn't a good idea (because you sometimes have huge delays on touch events being processed when slow paints cause paint timers to pile up).
So currently I am using the strategy given by user godexsoft at http://www.idevgames.com/forum/showthread.php?t=17058 (search for the post by godexsoft). Specifically, my render run loop is on the main thread and contains this:
while( CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.01f, FALSE) ==
kCFRunLoopRunHandledSource);
This line allows events like touch events and things related to comms to happen in between rendering of frames. It works, but I'd like to refine it further. Is there any way I can give priority to the touch events over other events (like comms related stuff)? If I could do that, I could reduce the 0.01f number and get a better frame rate. (I'm aware that this might mean comms would take longer to get back, but the touch events not lagging is pretty important).
This doesn't directly answer your question, but have you considered using CADisplayLink for scheduling redraws? It was introduced in iPhone OS 3.1.

OpenGL ES on iPhone: timer-based painting problems, jitteryness

I have an OpenGL ES 1.1 project on iPhone, based heavily on the empty OpenGL ES application given here:
http://iphonedevelopment.blogspot.com/2009/06/empty-opengl-es-application-project.html
I'm testing on a 3G (not 3GS) device, 8GB.
The paint loop in my app which does openGL operations is doing quite a lot each time it renders the screen. However, in situations with it doing the same thing each paint cycle, I'm seeing variable frame rates. I have set the NSTimer which fires the paint code to fire 30 times a second -- i.e. every 0.0333 of a second. The main problem is that whereas my actual paint code often takes approximately that amount of time to execute one paint (in terms of wall time), it varies, and sometimes it takes far longer, for no apparent reason. Using careful logging to report maximum time intervals when they occur, I can see that sometimes my paint has taken as long as 0.23 sec to complete - that's like 4FPS, which compared to 30FPS is like skipping 5 frames of animation/ user interaction, which isn't very acceptable.
At first I suspected my paint loop was snagging on some lock (there aren't many in there, because the GL render stuff in on the main thread (which is necessary AFAIK), as is incoming event handling) but some logging with finer granularity revealed that, in one paint code execution cycle, a large time elapsing over a bit of code that was doing basically hardly anything, and certainly not a GL operation.
So it seems a bit like my GL drawing thread (i.e. the main thread) just takes longer sometimes for no good reason. I have comms in my application and I disabled comms to see if that was the problem -- but I still see some "spikes" in execution time of my painting, when it's doing the same painting each time.
It's seems like another thread is just being switched to, mid-paint code, for ages, before returning to my paint code, on occaison.
Any ideas with how to analyse further what is going on? I know NSTimers aren't perfect and aren't at a guaranteed frequency, but the main issue here is that my actual paint cycle sometimes just takes forever, presumably because some other thread gets switched to....
Keep in mind that your application can seem to "hang" for no reason that has nothing to do with your "main loop". That's because you are multitasking... and in paticular, something as simple as your phone checking email can cause this sort of problem. One big cause, on the iPhone anyway, is when you move through different cell sites (like if you are on a subway or in a car) you can sometimes get spikes as it does... whatever it does.
If you are on an iPhone, try airplane mode and see if the problems go away.
-- David