I have recently updated my iPad2 to iOS 6.0.1 from 5.x and upgraded xcode to 4.5.2. Now when I build and run my game it runs smoothly at 60 fps. However when a a 3d model gets close to the screen the framerate now drops to 40fps and stays there even when the model moves away from the screen. Is there someway to overcome this or is it a bug with iOS 6.0.1 or xcode 4.5.2? Could this be some kind of power saving feature of iOS 6.0.1? Any help would be appreciated.
-
2What does "close to the screen" mean? What does Instruments tell you (Time Profiler, OpenGL ES Driver / Analysis) when you are running normally vs. your slower state? – Brad Larson Dec 10 '12 at 02:24
-
"is it a bug with iOS 6.0.1" You should always assume the problem is in your own code, until you can prove otherwise. – sosborn Dec 10 '12 at 02:30
-
I mean when the model is close to the viewing frustum (when model takes up most of the screen). I'm not very familiar with Instruments so I'll look into that tomorrow. – Patrick Herlihy Dec 10 '12 at 03:42
2 Answers
As far as I can tell there is no bug in iOS 6.0.1 or Xcode 4.5.2 that can cause this, but I'm just a working iOS developer, not the engineer in charge of quality control on these projects.
With the minimal information available in this question my first guess is that the model is being drawn with a mipmapped texture. When far from the camera smaller versions of the texture are used, but when it moves close to the camera larger versions of the textures are used. A possible check you can do is to turn off the textures for this model and checking performance. Yet, I'm making the assumption that you are using textures, so this suggestion may be way off base.
The best way to diagnose this problem is to use the latest OpenGL debugging and profiling tools available in Xcode 4.5. I suggest watching the session videos from last summer's WWDC on OpenGL for a start on how to use these tools.
Edit to comment on your posted shader:
Shaders can process fragments in parallel, but will reduce the number of parallel processes if the conditionals in a shader evaluate to different values across fragments. To quote page 156 of the OpenGL ES 2.0 Programming Guide:
GPUs typically execute a vertex shader with multiple vertices or a fragment shader with multiple fragments in parallel. The number of vertices or fragments that are executed in parallel will depend on the GPU's performance target. The bool_expression in the if and if-else conditional statements can have different values for the vertices or fragments being executed in parallel. This can impact performance as the number of vertices or fragments executed in parallel by the GPU is reduced. We recommend that for best performance, conditional statements should be used with bool_expression values that are the same for vertices or fragments being executed in parallel. This will be the case if a uniform expression is used.
Maybe GPU happily processes lots of fragments because your boolean values are the same for each fragment. Then the GPU gets fragments where the boolean is no longer evaluating the same, and it no longer processes fragments in parallel. Knowing that these can evaluate to different values, the GPU continues to process the fragments with less parallelism even after the models move further from the camera.
Your series of if statements clamp the values to specific states. Maybe writing an equation that will give similar results may fix the problem. Try something like:
df = (floor(mod((((df + 0.2) * 10.0) / 3.0), 4.0)) * 3.0) / 10.0;
I didn't actually compile a shader with this code, nor does it exactly match your ranges, so you may need to make some adjustments. But this should keep the parallelism up.

- 10,525
- 1
- 39
- 42
-
No the models have no texture. The framerate does not increase back up to 60fps when the model is drawn far from the viewing frustum. It just stays at a slow 40fps. This never happened until I upgraded ios and Xcode. If I have the camera zoomed out this never occurs. If I comment out the line that calls glDrawElements it never occurs either so I don't think it's a CPU processing issue. Which instrument should I use? The OpenGL one says it's not the graphics pipeline. – Patrick Herlihy Dec 17 '12 at 01:20
-
It appears to be the fragment shader. If I use a simple one that simply returns a color the framerate drop never happens. But when I use the one with lighting the framerate drops when the model is the size of the screen. I just don't know why the framerate doesn't increase when the model moves away from the viewing frustum. – Patrick Herlihy Dec 22 '12 at 14:31
-
-
`code`varying mediump vec3 EyespaceNormal; uniform highp vec3 DiffuseMaterial; uniform highp vec3 LightPosition; uniform highp vec3 AmbientMaterial; uniform highp vec3 SpecularMaterial; uniform highp float Shininess; void main(void) { highp vec3 N = normalize(EyespaceNormal); highp vec3 L = normalize(LightPosition); highp vec3 E = vec3(0.0, 0.0, 1.0); highp vec3 H = normalize(L + E); highp float df = max(0.0, dot(N, L)); highp float sf = max(0.0, dot(N, H)); sf = pow(sf, Shininess); if (df < 0.1) df = 0.0; else if (df < 0.3) df = 0.3; else if (df < 0.6) df = 0.6; else df = 1.0; – Patrick Herlihy Dec 23 '12 at 18:33
-
`code`lowp vec3 color = AmbientMaterial + df * DiffuseMaterial + sf * SpecularMaterial; gl_FragColor = vec4(color, 1.0); } If I comment out the conditionals the drop in framerate only happens when 2 or more models are rendered large. Once the framerate drop occurs it never goes back up even if I switch back to a basic shader. – Patrick Herlihy Dec 23 '12 at 18:33
-
-
Apple could have made an implementation change to OpenGL ES in iOS 6.0.1. The specification allows implementors to make such changes and still conform to the specification. Apple probably found an optimization that improves most cases, but degrades performance in this particular case. – Mr. Berna Dec 27 '12 at 15:31
-
Even when the conditionals are removed the framerate drop still occurs when 2 models are rendered close to the camera which would be acceptable if the framerate picked back up when they move away from the camera. I'm hoping the coming 6.1 update fixes this. – Patrick Herlihy Dec 28 '12 at 16:46
It seems the "problem" got fixed on iOS 7.
I was having exactly the same issue...installed the new OS this morning, and it seems the framerate issue has just dissapeared.
Now the framerate drops are consistent. It still drops of course if yo do too much GPU stuff...but it drops and recovers gradually back to 60 as the GPU has less operations to perform.
So in the end it seems it was some kind of "driver/OS issue" (no official confirmation though)

- 1
- 1
-
Yes I was quite please when I upgraded last night and the problem went away. I believe it was supposed to be an enhancement to either conserve battery or to keep a stable framerate in iOS6. – Patrick Herlihy Sep 19 '13 at 17:10