Reputation: 544
Seemingly at random (but typically consistent during any given program run), my presentRenderBuffer
call is very slow. I tracked it down to a call to glFlush()
which presentRenderBuffer
makes, so now I call glFlush()
right before presentRenderBuffer. I put a timer on glFlush()
, and it does one of two things, seemingly at random.
glFlush()
either
1) consistently takes 0.0003 seconds
OR
2) alternates between about 0.019 and 0.030 seconds
The weirdest thing is, this is independent of drawing code. Even when I comment out ALL drawing code so that all it does is call glClear()
, I still just randomly get one of the two results.
The drawing method is called by an CADisplayLink
with the following setup:
dLink = [[UIScreen mainScreen] displayLinkWithTarget:viewController selector:@selector(drawFrame)];
dLink.frameInterval = 1;
[dLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
I'm finding it impossible to pin down what causes one of the results to occur. Can anyone offer ideas?
Upvotes: 4
Views: 3223
Reputation: 544
I found what I think was the problem. The view controller that was attached to the EAGLView was NOT set as the root view controller of the window as it should have been. Instead, the view was manually added as a subview to the window. When this was remedied (along with a couple other related fixes), the drawFrame method now seems to sync up perfectly with the screen refresh. Success!
Upvotes: 1
Reputation: 170309
Performing exact timings on iOS OpenGL ES calls in general is a little tricky, due to the tile-based deferred renderers used for the devices. State changes, drawing, and other actions can be deferred until right before the scene is presented.
This can often make something like glFlush()
or a context's -presentRenderBuffer:
look to be very slow, when really it's just causing all of the deferred rendering to be performed at that point.
Your case where you comment out all drawing code but a glClear()
wouldn't be affected by this. The varying timings you present in your alternating example correspond roughly to 1/53 or 1/33 of a second, which seems to indicate to me that it might simply be blocking for long enough to match up to the screen refresh rate. CADisplayLink should keep you in sync with the screen refresh, but I could see your drawing sometimes being slightly off that.
Are you running this test on the main thread? There may be something causing a slight blocking of the main thread, throwing you slightly off the screen refresh timing. I've seen a reduction in this kind of oscillation when I moved my rendering to a background thread, but still had it be triggered by a CADisplayLink. Rendering speed also increased as I did this, particularly on the multicore iPad 2.
Finally, I don't believe you need to explicitly use glFlush()
when using OpenGL ES on iOS. Your EAGLContext's presentRenderbuffer:
method should be all that is required to render your frame to the screen. I don't see a single instance of glFlush()
in my OpenGL ES application here. It may be redundant in your case.
Upvotes: 3