iOS:处理应用程序转换期间在后台线程上运行的 OpenGL 代码



我正在开发一个iOS应用程序,例如单击按钮,它会启动多个线程,每个线程执行一段Open GL代码。这些线程要么设置了不同的EAGLContext,要么如果它们使用相同的EAGLContext,那么它们就会同步(即2个线程不会并行设置相同的EAGLContext(。

现在假设应用程序进入后台。根据Apple的文档,我们应该在回调中停止所有OpenGL调用applicationWillResignActive:以便在调用applicationDidEnterBackground:时不再进行GL调用。

我正在使用dispatch_queues来创建后台线程。例如:

__block Byte* renderedData; // some memory already allocated
dispatch_sync(glProcessingQueue, ^{
[EAGLContext setCurrentContext:_eaglContext];
glViewPort(...)
glBindFramebuffer(...)
glClear(...)
glDrawArrays(...)
glReadPixels(...) // read in renderedData
}
use renderedData for something else

我的问题是 - 如何处理applicationWillResignActive:以便任何此类后台 GL 调用不仅可以停止,还可以在applicationDidBecomeActive:上恢复?我应该等待当前正在运行的块完成后再从applicationWillResignActive:返回吗?还是我应该暂停glProcessingQueue并返回?

我还读到,当应用程序以其他方式中断时,情况类似,例如显示警报、电话等。

我可以在任何时间点有多个这样的线程,可能由多个 ViewController 调用,所以我正在寻找一些可扩展的解决方案或设计模式。

在我看来,你需要暂停一个线程或杀死它。

如果你杀死它,你需要确保释放所有资源,这意味着最有可能再次调用openGL。在这种情况下,实际上最好只是等待块完成执行。这意味着块不能花太长时间才能完成,这是无法保证的,并且由于您有多个上下文和线程,因此实际上可能会出现问题。

所以暂停似乎更好。我不确定是否有直接的 API 来暂停线程,但您可以让它等待。也许类似于这个系统的s系统可以提供帮助。

链接的示例似乎完全处理了您想要的内容;它已经检查了当前线程并锁定了该线程。我想你可以把它打包到一些工具中作为静态方法或 C 函数,只要你有信心可以暂停线程,你就会简单地做一些事情:

dispatch_sync(glProcessingQueue, ^{
[EAGLContext setCurrentContext:_eaglContext];
[ThreadManager pauseCurrentThreadIfNeeded];
glViewPort(...)
glBindFramebuffer(...)
[ThreadManager pauseCurrentThreadIfNeeded];
glClear(...)
glDrawArrays(...)
glReadPixels(...) // read in renderedData
[ThreadManager pauseCurrentThreadIfNeeded];
}

如果使用主线程,您可能仍会遇到问题。您可能希望跳过暂停,否则您的系统可能永远不会再次唤醒(但不确定,请尝试一下(。

所以现在你看到你的ThreadManager的界面是这样的:

+ (void)pause {
__threadsPaused = YES;
}
+ (void)resume {
__threadsPaused = NO;
}
+ (void)pauseCurrentThreadIfNeeded {
if(__threadsPaused) {
// TODO: insert code for locking until __threadsPaused becomes false
}
}

让我们知道您的发现。

最新更新