【问题标题】:How to avoid crash "OpenGL rendering while app in background state"如何避免崩溃“应用程序处于后台状态时的 OpenGL 渲染”
【发布时间】:2020-01-15 21:52:15
【问题描述】:

我最近收到了很多关于 Fabric 的崩溃报告。它说根据此处显示的堆栈跟踪,看起来触发 OpenGL 渲染的新调用发生在应用程序转换为或从背景状态转换时。如果您在应用程序委托的方法中设置 OpenGL 绘图,请确保您只在 applicationDidBecomeActive: 中这样做,而不是在 application:willFinishLaunchingWithOptions: 或 application:didFinishLaunchingWithOptions: 中这样做。

0   libGPUSupportMercury.dylib  gpus_ReturnNotPermittedKillClient
1   AGXGLDriver (Missing)
2   libGPUSupportMercury.dylib  gpusSubmitDataBuffers
3   AGXGLDriver (Missing)
4   WebCore WebCore::GraphicsContext3D::reshape(int, int) + 580
5   WebCore WebCore::WebGLRenderingContextBase::initializeNewContext() + 936
6   WebCore WebCore::WebGLRenderingContextBase::WebGLRenderingContextBase(WebCore::CanvasBase&, WTF::Ref<WebCore::GraphicsContext3D, WTF::DumbPtrTraits<WebCore::GraphicsContext3D> >&&, WebCore::GraphicsContext3DAttributes) + 660
7   WebCore WebCore::WebGLRenderingContext::create(WebCore::CanvasBase&, WTF::Ref<WebCore::GraphicsContext3D, WTF::DumbPtrTraits<WebCore::GraphicsContext3D> >&&, WebCore::GraphicsContext3DAttributes) + 84
8   WebCore WebCore::WebGLRenderingContextBase::create(WebCore::CanvasBase&, WebCore::GraphicsContext3DAttributes&, WTF::String const&) + 1416
9   WebCore WebCore::HTMLCanvasElement::getContext(JSC::ExecState&, WTF::String const&, WTF::Vector<JSC::Strong<JSC::Unknown>, 0ul, WTF::CrashOnOverflow, 16ul>&&) + 904
10  WebCore  WebCore::jsHTMLCanvasElementPrototypeFunctionGetContext(JSC::ExecState*) + 424
11  JavaScriptCore  llint_entry + 89612
12  JavaScriptCore  llint_entry + 82980
13  JavaScriptCore  llint_entry + 82980
14  JavaScriptCore  llint_entry + 82980
15  JavaScriptCore  llint_entry + 82980
16  JavaScriptCore  llint_entry + 82980
17  JavaScriptCore  vmEntryToJavaScript + 268
18  JavaScriptCore  JSC::Interpreter::executeCall(JSC::ExecState*, JSC::JSObject*, JSC::CallType, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&) + 424
19  JavaScriptCore  JSC::profiledCall(JSC::ExecState*, JSC::ProfilingReason, JSC::JSValue, JSC::CallType, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&, WTF::NakedPtr<JSC::Exception>&) + 200
20  WebCore  WebCore::JSExecState::profiledCall(JSC::ExecState*, JSC::ProfilingReason, JSC::JSValue, JSC::CallType, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&, WTF::NakedPtr<JSC::Exception>&) + 140
21  WebCore  WebCore::ScheduledAction::executeFunctionInContext(JSC::JSGlobalObject*, JSC::JSValue, WebCore::ScriptExecutionContext&) + 424
22  WebCore  WebCore::ScheduledAction::execute(WebCore::Document&) + 144
23  WebCore  WebCore::DOMTimer::fired() + 816
24  WebCore  WebCore::ThreadTimers::sharedTimerFiredInternal() + 216
25  WebCore  WebCore::timerFired(__CFRunLoopTimer*, void*) + 28
26  CoreFoundation  __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 28
27  CoreFoundation  __CFRunLoopDoTimer + 864
28  CoreFoundation  __CFRunLoopDoTimers + 248
29  CoreFoundation  __CFRunLoopRun + 1844
30  CoreFoundation  CFRunLoopRunSpecific + 436
31  WebCore RunWebThread(void*) + 600
32  libsystem_pthread.dylib _pthread_body + 128
33  libsystem_pthread.dylib _pthread_start + 44
34  libsystem_pthread.dylib thread_start + 4

如何找到代码崩溃的地方?

【问题讨论】:

    标签: ios objective-c opengl-es google-fabric


    【解决方案1】:

    据我所知苹果不支持 iOS 13 或 10.15 的 openGL,请尝试将其转换为金属

    “重要提示:OpenGL 在 macOS 10.14 中已弃用。要在 GPU 上创建高性能代码,请改用 Metal 框架。请参阅 Metal。”

    https://developer.apple.com/library/archive/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_intro/opengl_intro.html

    【讨论】:

    • 是的,我没有使用 openGL。
    【解决方案2】:

    GLKViewController 在 ios 13 中运行良好。至于你的问题,我是通过以下方式完成的。

    在您的应用委托中。

    - (void)applicationWillResignActive:(UIApplication *)application
    {
            [[NSNotificationCenter defaultCenter] postNotificationName:@".applicationWillResignActive" object:nil];
    }
    
    - (void)applicationDidBecomeActive:(UIApplication *)application
    {
            [[NSNotificationCenter defaultCenter] postNotificationName:@".applicationDidBecomeActive" object:nil];
    }
    

    然后在您的渲染视图控制器中。

    - (void)viewWillAppear:(BOOL)animated
    {
            [super viewWillAppear:animated];
            [[NSNotificationCenter defaultCenter] addObserver:self
                                                     selector:@selector(applicationWillResignActive:)
                                                         name:@".applicationWillResignActive"
                                                       object:nil];
            [[NSNotificationCenter defaultCenter] addObserver:self
                                                     selector:@selector(applicationDidBecomeActive:)
                                                         name:@".applicationDidBecomeActive"
                                                       object:nil];
             self.preferredFramesPerSecond = 30;
             self.pauseOnWillResignActive = NO;
             self.resumeOnDidBecomeActive = NO;
    }
    

    GLKit 有自己的机制来处理进入后台(即 pauseOnWillResignActive 属性),但它对我来说效果不佳。我怀疑是因为它只会停止渲染计时器,但不会使用 glFinish() 或 glFlush() 刷新 gl 操作队列。所以我自己处理了。

    - (void) viewDidDisappear:(BOOL)animated
    {
            [super viewDidDisappear:animated];
            [[NSNotificationCenter defaultCenter] removeObserver:self name:@".applicationDidBecomeActive" object:nil];
            [[NSNotificationCenter defaultCenter] removeObserver:self name:@".applicationWillResignActive" object:nil];
    }
    
    - (void)applicationWillResignActive:(NSNotification *)note
    {
            [self suspend];
    }
    
    - (void)applicationDidBecomeActive:(NSNotification *)note
    {
            [self resume];
    }
    

    现在您的暂停和恢复方法可能如下所示。

    -(void) suspend
    {
            self.suspended = YES;
            glFinish();
    }
    
    -(void) resume
    {
            if (self.suspended) {
                    self.suspended = NO;
                    [(GLKView *)self.view display];
            }
    }
    

    PS。虽然它工作正常,但这是一个相当古老的 API(GLKit)。我真的建议你弄清楚如何使用金属。

    【讨论】:

    • 我从未在我的应用程序中使用过 GLKViewController。我刚刚使用了第三个库“Lottie”。
    • 那么至少可以拦截 applicationWillResignActive() 并在其中发出 glFinish() 。如果不工作 - 请检查您的“Lottie”的渲染周期。它应该像大多数 api 一样具有某种 pause() 和 resume()。
    猜你喜欢
    • 1970-01-01
    • 2016-12-07
    • 2021-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多