I'm working on a iPhone application which is hybrid OpenGL ES and regular iPhone UI. This means there is an EAGLView
greeting the user, then some regular UIView
s that gets pushed over it (there is a UINavigationController
as root controller).
I've got a random (but very frequent) crash when navigating back from a subview. Here is a (...censored...) stack trace, from a Release build, but it crashes just the same in Debug.
#0 0x006863d0 in GetFBOBuffers ()
#1 0x00660120 in TerminateScene ()
#2 0x00660314 in FlushScene ()
#3 0x00660cd4 in FlushHW ()
#4 0x0066a6a0 in GLESPresentView ()
#5 0x323533a4 in -[EAGLContext presentRenderbuffer:] ()
#6 0x000026c0 in -[EAGLView presentFramebuffer] (self=0x11ce60, _cmd=<value temporarily unavailable, due to optimizations>) at (...)/Classes/EAGLView.m:157
#7 0x00004fdc in -[(...)ViewController drawFrame] (self=<value temporarily unavailable, due to optimizations>, _cmd=<value temporarily unavailable, due to optimizations>) at (...) ViewController.m:380
#8 0x336ebd9a in __NSFireTimer ()
#9 0x323f54c2 in CFRunLoopRunSpecific ()
#10 0x323f4c1e in CFRunLoopRunInMode ()
#11 0x335051c8 in GSEventRunModal ()
#12 0x324a6c30 in -[UIApplication _run] ()
#13 0x324a5230 in UIApplicationMain ()
#14 0x0000214c in main (argc=1, argv=0x2ffff568) at (...)/main.m:14
Here is a list of things I know:
So I know it must be some kind of data that gets released or destroyed, but I don't know how to find which. Any tips and tricks would be appreciated ;-)
UPDATE:
After setting some breakpoints, moving along the stack, poking at various variables, I've found the reason for the crash, but not yet the source.
In EAGLView, in the method presentFramebuffer
where and when the crash occurs, the colorRenderBuffer ivar is 0 if I can believe gdb, even though trying to breakpoint when it's 0 doesn't seem to work.
It seems the deleteFrameBuffer
call from layoutSubviews
isn't matched by a createFramebuffer
.
UPDATE 2:
Lots of breakpoints later... I've found a wrong situation: [EAGLView layoutSubviews]
gets called in the middle of a drawFrame
! So the buffers get deleted while in use... BAM!
Now how do I fix that?
I haven't found a 'proper' fix yet, but I've added a workaround.
In presentFramebuffer
, I set a boolean around the rendering :
if (context)
{
isRendering_PATCH_VARIABLE = YES;
[EAGLContext setCurrentContext:context];
glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer);
success = [context presentRenderbuffer:GL_RENDERBUFFER_OES];
glBindRenderbufferOES(GL_RENDERBUFFER_OES, 0);
isRendering_PATCH_VARIABLE = NO;
}
and in deleteFramebuffer
, I check this boolean:
if (isRendering_PATCH_VARIABLE)
{
NSLog(@"GOTCHA - CRASH AVOIDED");
}
if (context && !isRendering_PATCH_VARIABLE)
{
// ...
}
It doesn't seem to have side-effects (like broken display, etc), so I'll leave it like that for the moment.
Here's wild guess based on something I did recently.
What I did was break up the loading stage. I wanted to show a progress bar as I loaded up a number of resources - it's a slow process so I wanted to provide some user feedback.
My first step was similar to the OpenGL ES example provided with Xcode in that I called an init on an ES?Renderer. But after that I stalled the process so I could load other resources.
To cut a long story short, because of my re-arrangement of code the [EAGLView layoutSubviews]
was never called after my initialisation. I didn't get a crash, but nothing much happened after this point.
What I had to do was that after I finished initialising OpenGL's context and loading all my data, I had to manually call the [EAGLView layoutSubviews]
. This seemed to fix things for me.
Maybe you need to try something similar. After you initialise your OpenGL context and data, call the [EAGLView layoutSubviews]
before you get into your drawing routines. Maybe this will stop this call again reappearing in your rendering step and crashing.
A stab in the dark: Your device gets low on memory, the application receives a memory warning and the controller responsible for the GL view releases the view, which is something you did not count with? Does the problem go away when you suppress the default didReceiveMemoryWarning
?
- (void) didReceiveMemoryWarning { /* nothing we can do, sorry */ }
…or maybe you are calling OpenGL from another thread that does not have the context?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With