From 6511773fed2aa50cbd89d340da278b84b0365a0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20G=C3=B6decke?= Date: Mon, 11 Mar 2024 14:11:20 +0100 Subject: [PATCH] fix(ios): fix crash when reloading app (#36) Co-authored-by: Marc Rousavy --- package/cpp/core/EngineWrapper.cpp | 41 +++++++++++++++++--------- package/ios/src/MetalSurfaceProvider.h | 6 ++++ 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/package/cpp/core/EngineWrapper.cpp b/package/cpp/core/EngineWrapper.cpp index 86772596..5a935ac1 100644 --- a/package/cpp/core/EngineWrapper.cpp +++ b/package/cpp/core/EngineWrapper.cpp @@ -74,9 +74,10 @@ EngineWrapper::EngineWrapper(std::shared_ptr choreographer, std:: _engine, resourceLoaderPtr, [stbProvider, ktx2Provider](const std::shared_ptr& engine, gltfio::ResourceLoader* resourceLoader) { Logger::log(TAG, "Destroying resource loader..."); + resourceLoader->evictResourceData(); + delete resourceLoader; delete stbProvider; delete ktx2Provider; - delete resourceLoader; }); // Setup filament: @@ -123,29 +124,37 @@ void EngineWrapper::setSurfaceProvider(std::shared_ptr surfaceP } auto queue = _jsDispatchQueue; - auto sharedThis = shared(); + std::weak_ptr weakSelf = shared(); SurfaceProvider::Callback callback{.onSurfaceCreated = - [=](std::shared_ptr surface) { + [queue, weakSelf](std::shared_ptr surface) { queue->runOnJS([=]() { - Logger::log(TAG, "Initializing surface..."); - sharedThis->setSurface(surface); + auto sharedThis = weakSelf.lock(); + if (sharedThis != nullptr) { + Logger::log(TAG, "Initializing surface..."); + sharedThis->setSurface(surface); + } }); }, .onSurfaceSizeChanged = - [queue, sharedThis](std::shared_ptr surface, int width, int height) { + [queue, weakSelf](std::shared_ptr surface, int width, int height) { queue->runOnJS([=]() { - Logger::log(TAG, "Updating Surface size..."); - sharedThis->surfaceSizeChanged(width, height); - sharedThis->synchronizePendingFrames(); + auto sharedThis = weakSelf.lock(); + if (sharedThis != nullptr) { + Logger::log(TAG, "Updating Surface size..."); + sharedThis->surfaceSizeChanged(width, height); + sharedThis->synchronizePendingFrames(); + } }); }, .onSurfaceDestroyed = - [=](std::shared_ptr surface) { + [queue, weakSelf](std::shared_ptr surface) { // TODO(Marc): When compiling in debug mode we get an assertion error here, because we are // destroying the surface from the wrong thread. queue->runOnJSAndWait([=]() { - Logger::log(TAG, "Destroying surface..."); - sharedThis->destroySurface(); + auto sharedThis = weakSelf.lock(); + if (sharedThis != nullptr) { + sharedThis->destroySurface(); + } }); }}; _surfaceListener = surfaceProvider->addOnSurfaceChangedListener(callback); @@ -186,6 +195,12 @@ void EngineWrapper::surfaceSizeChanged(int width, int height) { } void EngineWrapper::destroySurface() { + if (_swapChain == nullptr) { + // Surface is already destroyed / never existed. + return; + } + + Logger::log(TAG, "Destroying surface..."); _choreographer->stop(); _choreographerListener->remove(); _renderCallback = std::nullopt; @@ -207,8 +222,6 @@ void EngineWrapper::renderFrame(double timestamp) { return; } - _resourceLoader->asyncUpdateLoad(); - if (_startTime == 0) { _startTime = timestamp; } diff --git a/package/ios/src/MetalSurfaceProvider.h b/package/ios/src/MetalSurfaceProvider.h index b7b7ddf7..d8d80d28 100644 --- a/package/ios/src/MetalSurfaceProvider.h +++ b/package/ios/src/MetalSurfaceProvider.h @@ -18,13 +18,19 @@ class MetalSurfaceProvider : public SurfaceProvider { public: explicit MetalSurfaceProvider(CAMetalLayer* layer) { _layer = layer; + // Surface has been created _surface = std::make_shared(layer); + this->onSurfaceCreated(_surface); + _observer = [[BlockObserver alloc] initWithBlock:^(NSDictionary* change, void* context) { + // Surface size has changed this->onSurfaceChanged(_surface, _surface->getWidth(), _surface->getHeight()); }]; [_layer addObserver:_observer forKeyPath:@"drawableSize" options:NSKeyValueObservingOptionNew context:NULL]; } ~MetalSurfaceProvider() { + // Surface will be destroyed + this->onSurfaceDestroyed(_surface); [_layer removeObserver:_observer forKeyPath:@"drawableSize"]; }