앱이 백그라운드로 이동하자마자 OpenGL 기능 호출을 중단해야합니다. 하지만 어떻게 든 사용자가 홈 버튼을 누르면 OpenGL을 중지하려는 모든 노력이 실패하고 종종 내 앱이 중단됩니다 (하지만 항상 그런 것은 아닙니다).애플 backgrounding하는 동안 동시 OpenGL 그리기를 중단하는 방법?
이
예외 유형과 충돌 : EXC_BAD_ACCESS 코드 : KERN_INVALID_ADDRESS를 0x1로 libGPUSupportMercury.dylib gpus_ReturnNotPermittedKillClient
에서 나의 이해하는 앱 후에는 OpenGL 함수를 호출하면됩니다하지 전경에 더 이상 응용 프로그램 것 GPU를 앱에서 사용할 수 없기 때문에 충돌이 발생합니다. OpenGL은로 렌더링
보기는 발송 대기열 그것은있는 UIScrollView와 병렬 렌더링하는
self.drawingQueue = dispatch_queue_create("openglRenderQueue", DISPATCH_QUEUE_SERIAL);
있다. 따라서 GCD semaphore을 사용하면 큐에서 UIScrollView를 기다릴 수 있습니다. 큐를 렌더링하고있는 UIScrollView 기다릴 세마포어를 사용하여 일련의
CADisplayLink *dl = [[UIScreen mainScreen] displayLinkWithTarget:self selector:@selector(update)];
[dl addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
self.displayLink = displayLink;
Update 메소드 드로잉 수행 계산 비동기 :
self.renderSemaphore = dispatch_semaphore_create(1);
난 runloop를 업데이트하는 CADisplayLink를 생성한다. 마침내 메인 스레드에서 동기화를 커밋합니다.
- (void)update {
dispatch_async(drawingQueue, ^{
if (dispatch_semaphore_wait(renderSemaphore, DISPATCH_TIME_NOW) != 0) {
return;
}
@autoreleasepool {
[EAGLContext setCurrentContext:context];
glBindFramebufferOES(GL_FRAMEBUFFER_OES, framebuffer);
glViewport(0, 0, width, height);
glMatrixMode(GL_MODELVIEW);
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
// Quickly grab the target game state for rendering
GameState state = targetState;
[sprite drawState:state];
dispatch_sync(dispatch_get_main_queue(), ^{
if ([self canRender]) {
BOOL isAnimating = [self isAnimating];
if (isAnimating && displayLink) {
[EAGLContext setCurrentContext:context];
glBindRenderbufferOES(GL_RENDERBUFFER_OES, renderbuffer);
if (displayLink != nil) {
[context presentRenderbuffer:GL_RENDERBUFFER_OES];
}
}
}
});
}
dispatch_semaphore_signal(renderSemaphore);
});
}
업데이트 방법은 렌더링 할 수있는 경우 주 스레드를 검사합니다. 체크는 다음과 같습니다
이- (BOOL)canRender {
UIApplicationState appState = [[UIApplication sharedApplication] applicationState];
return (appState != UIApplicationStateBackground && appState != UIApplicationStateInactive);
}
내가 가장 의심 한 것은 큐를 중단하는 동시성 문제입니다. 비동기이기 때문에 표시 링크를 중지 한 후에도 블록이 실행됩니다. 지금
__block BOOL canRender = YES;
dispatch_sync(dispatch_get_main_queue(), ^{
canRender = [self canRender];
});
if (!canRender) {
return;
}
OK
하지만 실행 렌더링의 시작 부분에이 검사를 할 상상 :
그래서 내가 뭘없는 것은 내가이 비동기 블록에서 OpenGL을 함수를 호출하기 전에 나는 또한 -canRender 확인해야한다는 생각 고리.-canRender
에 YES라고 표시되어 있습니다. 그런 다음
[sprite drawState:state];
으로 전화합니다. 이 메서드는 많은 gl 함수를 호출합니다. 나는 이것이 근본적인 문제라고 생각한다. 응용 프로그램이 여전히 포 그라운드에있는 경우 내 비동기 블록이 주 스레드에서 검사하더라도 3 초 후에 복잡한 그림을 그리기 위해 비동기를 계속하면 응용 프로그램이 백그라운드 상태 및 CRASH 상태가 될 수 있습니다.
그래서 모든 단일 gl 함수 호출 전에 주 스레드에서 -canRender를 실행해도 나중에 분할 된 나노초가 백그라운드에 있고 충돌 할 수 있습니다.
OpenGL을 내부에서 종료하여 해당 기능 호출을 무시하는 방법이 있습니까? 나는 마무리 방법에 대해 들었다. 나는 그것을 폐쇄해야 할 것이다. 그러나 어떻게?