Starting iOS 11, I have been noticing OpenGL-ES crashes, when we call display method on GLKView. We have made sure GLKView and EAGLContext are properly instantiated and called from appropriate thread.
Below is the stack trace related to the crash.
Exception Type: SIGABRT
Exception Codes: #0 at 0x182c042e8
Crashed Thread: 0
Thread 0 Crashed:
0 libsystem_kernel.dylib 0x0000000182c042e8 __pthread_kill + 8
1 libsystem_pthread.dylib 0x0000000182d1d748 pthread_kill$VARIANT$armv81 + 356
2 libsystem_c.dylib 0x0000000182b72fbc abort + 136
3 Metal 0x0000000184e15a9c MTLReleaseAssertionFailure + 268
4 AppleMetalGLRenderer 0x00000001a269af18 GLDTextureRec::allocMetalTexture() + 724
5 AppleMetalGLRenderer 0x00000001a269b010 GLDTextureRec::loadPrivateTexture(unsigned int, unsigned short*) + 52
6 AppleMetalGLRenderer 0x00000001a269917c GLDTextureRec::update(unsigned int, unsigned short*) + 164
7 AppleMetalGLRenderer 0x00000001a2695e98 GLDFramebufferRec::load() + 124
8 AppleMetalGLRenderer 0x00000001a2696224 gldLoadFramebuffer + 12
9 GLEngine 0x00000001a345e84c gleCheckFramebufferStatus + 112
10 GLEngine 0x00000001a340bb44 glCheckFramebufferStatusEXT_Exec + 120
11 GLKit 0x000000018feef330 -[GLKView _createFramebuffer] + 1144
12 GLKit 0x000000018feef660 -[GLKView _setFramebuffer:] + 128
13 GLKit 0x000000018feef8ac -[GLKView _display:] + 84
This is the Xcode console output I got when i was able to reproduce that crash.
GTML desc[0] t=4 f=70 w=1001 h=944 d=1 m=1 s=4 a=1 r=1 u=4
failed assertion metalTexture != nil at line 863 in allocMetalTexture
Going by the stack trace, it looks like the crash is happening when the GLKit is creating the frame buffer object for the GLKView, before it calls us back at the draw method. I am not entirely what could be the potential root cause for the issue.
Unfortunately, this crash is very hard to reproduce and not happening consistently.
Some important code snippets from the code.
Setup GLKView and EAGLContext:
self.eaglContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2 sharegroup:self.resources.shareGroup];
// Create the actual OpenGL view
self.glView = [[GLKView alloc] initWithFrame:self.frame context:self.eaglContext];
self.glView.delegate = self;
self.glView.enableSetNeedsDisplay = NO;
self.glView.contentScaleFactor = self.screenDensity;
self.glView.drawableMultisample = GLKViewDrawableMultisample4X;
[EAGLContext setCurrentContext:self.eaglContext];
//Load custom textures
[EAGLContext setCurrentContext:nil];
//Now, I created vertexArrayObjects using glGenVertexArrays, enable blending etc, setup vertexBufferObjects for vertices and indices using glGenBuffers method.
Now, when I am ready to draw the content, I am calling the below code. I also had checks to make sure eaglContext, GLKView and also same thread is used as where the EAGLContext is created.
[EAGLContext setCurrentContext:self.eaglContext];
if(!CGRectIsEmpty(self.glView.bounds) && !self.hidden) {
[self.glView display];
}
[EAGLContext setCurrentContext:nil];
To my knowledge, we are not needed to call bindDrawable as I am using GLKView provided default frame buffer itself.
Any insights/help is truly appreciated.