From 7a28a6e80db533125f62ddb18e41257ad9caf234 Mon Sep 17 00:00:00 2001 From: William Candillon Date: Mon, 18 Nov 2024 23:51:25 +0100 Subject: [PATCH] =?UTF-8?q?fix(=F0=9F=8D=8F):=20Fix=20performance=20regres?= =?UTF-8?q?sion=20on=20iOS=20(#2744)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fixes #2743 In v1.5.3, we introduced a regression where we would request the next frame twice leading to frame drop in half. --- packages/skia/cpp/rnskia/DawnContext.h | 42 +++++++++---------- packages/skia/cpp/rnskia/DawnUtils.h | 3 +- .../ios/RNSkia-iOS/RNSkMetalCanvasProvider.h | 3 +- .../ios/RNSkia-iOS/RNSkMetalCanvasProvider.mm | 41 ++++++++---------- .../ios/RNSkia-iOS/SkiaMetalSurfaceFactory.h | 30 +++++++++---- .../ios/RNSkia-iOS/SkiaMetalSurfaceFactory.mm | 20 --------- 6 files changed, 64 insertions(+), 75 deletions(-) diff --git a/packages/skia/cpp/rnskia/DawnContext.h b/packages/skia/cpp/rnskia/DawnContext.h index bfeb7196f9..82ccc8cbb8 100644 --- a/packages/skia/cpp/rnskia/DawnContext.h +++ b/packages/skia/cpp/rnskia/DawnContext.h @@ -36,8 +36,8 @@ struct AsyncContext { }; struct SharedTextureContext { - wgpu::SharedTextureMemory sharedTextureMemory; - wgpu::Texture texture; + wgpu::SharedTextureMemory sharedTextureMemory; + wgpu::Texture texture; }; static void @@ -111,7 +111,7 @@ class DawnContext { int height = static_cast(IOSurfaceGetHeight(ioSurface)); #else wgpu::SharedTextureMemoryAHardwareBufferDescriptor platformDesc; - auto ahb = (AHardwareBuffer*)buffer; + auto ahb = (AHardwareBuffer *)buffer; platformDesc.handle = ahb; platformDesc.useExternalFormat = true; AHardwareBuffer_Desc adesc; @@ -122,13 +122,16 @@ class DawnContext { wgpu::SharedTextureMemoryDescriptor desc = {}; desc.nextInChain = &platformDesc; - wgpu::SharedTextureMemory memory = backendContext.fDevice.ImportSharedTextureMemory(&desc); + wgpu::SharedTextureMemory memory = + backendContext.fDevice.ImportSharedTextureMemory(&desc); wgpu::TextureDescriptor textureDesc; textureDesc.format = DawnUtils::PreferredTextureFormat; textureDesc.dimension = wgpu::TextureDimension::e2D; - textureDesc.usage = wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::CopySrc; - textureDesc.size = {static_cast(width), static_cast(height), 1}; + textureDesc.usage = + wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::CopySrc; + textureDesc.size = {static_cast(width), + static_cast(height), 1}; wgpu::Texture texture = memory.CreateTexture(&textureDesc); @@ -137,26 +140,23 @@ class DawnContext { beginAccessDesc.fenceCount = 0; bool success = memory.BeginAccess(texture, &beginAccessDesc); - if (success) { - skgpu::graphite::BackendTexture betFromView = skgpu::graphite::BackendTextures::MakeDawn(texture.Get()); - auto result = SkImages::WrapTexture( - getRecorder(), - betFromView, - DawnUtils::PreferedColorType, - kPremul_SkAlphaType, - nullptr, - [](void* context) { + if (success) { + skgpu::graphite::BackendTexture betFromView = + skgpu::graphite::BackendTextures::MakeDawn(texture.Get()); + auto result = SkImages::WrapTexture( + getRecorder(), betFromView, DawnUtils::PreferedColorType, + kPremul_SkAlphaType, nullptr, + [](void *context) { auto ctx = static_cast(context); wgpu::SharedTextureMemoryEndAccessState endState = {}; ctx->sharedTextureMemory.EndAccess(ctx->texture, &endState); delete ctx; - }, - new SharedTextureContext{memory, texture} - ); - return result; - } + }, + new SharedTextureContext{memory, texture}); + return result; + } if (!success) { - return nullptr; + return nullptr; } return nullptr; } diff --git a/packages/skia/cpp/rnskia/DawnUtils.h b/packages/skia/cpp/rnskia/DawnUtils.h index 78f9573e5f..588c29bace 100644 --- a/packages/skia/cpp/rnskia/DawnUtils.h +++ b/packages/skia/cpp/rnskia/DawnUtils.h @@ -90,7 +90,8 @@ createDawnBackendContext(dawn::native::Instance *instance) { features.push_back(wgpu::FeatureName::SharedTextureMemoryIOSurface); } #else - if (adapter.HasFeature(wgpu::FeatureName::SharedTextureMemoryAHardwareBuffer)) { + if (adapter.HasFeature( + wgpu::FeatureName::SharedTextureMemoryAHardwareBuffer)) { features.push_back(wgpu::FeatureName::SharedTextureMemoryAHardwareBuffer); } #endif diff --git a/packages/skia/ios/RNSkia-iOS/RNSkMetalCanvasProvider.h b/packages/skia/ios/RNSkia-iOS/RNSkMetalCanvasProvider.h index 3bc5fa1e4c..41ae5a7a0e 100644 --- a/packages/skia/ios/RNSkia-iOS/RNSkMetalCanvasProvider.h +++ b/packages/skia/ios/RNSkia-iOS/RNSkMetalCanvasProvider.h @@ -30,8 +30,7 @@ class RNSkMetalCanvasProvider : public RNSkia::RNSkCanvasProvider { private: std::shared_ptr _context; - float _width = -1; - float _height = -1; + std::unique_ptr _ctx = nullptr; #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunguarded-availability-new" CAMetalLayer *_layer; diff --git a/packages/skia/ios/RNSkia-iOS/RNSkMetalCanvasProvider.mm b/packages/skia/ios/RNSkia-iOS/RNSkMetalCanvasProvider.mm index 7cba58f48c..1035d82bb9 100644 --- a/packages/skia/ios/RNSkia-iOS/RNSkMetalCanvasProvider.mm +++ b/packages/skia/ios/RNSkia-iOS/RNSkMetalCanvasProvider.mm @@ -36,19 +36,23 @@ /** Returns the scaled width of the view */ -float RNSkMetalCanvasProvider::getScaledWidth() { return _width; }; +float RNSkMetalCanvasProvider::getScaledWidth() { + return _ctx ? _ctx->getWidth() : -1; +}; /** Returns the scaled height of the view */ -float RNSkMetalCanvasProvider::getScaledHeight() { return _height; }; +float RNSkMetalCanvasProvider::getScaledHeight() { + return _ctx ? _ctx->getHeight() : -1; +}; /** Render to a canvas */ bool RNSkMetalCanvasProvider::renderToCanvas( const std::function &cb) { - if (_width <= 0 || _height <= 0) { + if (!_ctx) { return false; } @@ -72,33 +76,24 @@ // rendering and not wait until later - we've seen some example of memory // usage growing very fast in the simulator without this. @autoreleasepool { - id currentDrawable = [_layer nextDrawable]; - if (currentDrawable == nullptr) { - return false; - } -#if defined(SK_GRAPHITE) - auto ctx = RNSkia::DawnContext::getInstance().MakeWindow( - (__bridge void *)_layer, _width, _height); -#else - auto ctx = MetalContext::getInstance().MakeWindow(_layer, _width, _height); -#endif - auto skSurface = ctx->getSurface(); - SkCanvas *canvas = skSurface->getCanvas(); + auto surface = _ctx->getSurface(); + auto canvas = surface->getCanvas(); cb(canvas); - - if (auto dContext = GrAsDirectContext(skSurface->recordingContext())) { - dContext->flushAndSubmit(); - } - - ctx->present(); + _ctx->present(); } return true; }; void RNSkMetalCanvasProvider::setSize(int width, int height) { _layer.frame = CGRectMake(0, 0, width, height); - _width = width * _context->getPixelDensity(); - _height = height * _context->getPixelDensity(); + auto w = width * _context->getPixelDensity(); + auto h = height * _context->getPixelDensity(); +#if defined(SK_GRAPHITE) + _ctx = RNSkia::DawnContext::getInstance().MakeWindow((__bridge void *)_layer, + w, h); +#else + _ctx = MetalContext::getInstance().MakeWindow(_layer, w, h); +#endif _requestRedraw(); } diff --git a/packages/skia/ios/RNSkia-iOS/SkiaMetalSurfaceFactory.h b/packages/skia/ios/RNSkia-iOS/SkiaMetalSurfaceFactory.h index 920f5b873c..7107066562 100644 --- a/packages/skia/ios/RNSkia-iOS/SkiaMetalSurfaceFactory.h +++ b/packages/skia/ios/RNSkia-iOS/SkiaMetalSurfaceFactory.h @@ -11,9 +11,19 @@ #pragma clang diagnostic ignored "-Wdocumentation" #import "include/core/SkCanvas.h" +#import "include/core/SkColorSpace.h" + #import #import + +#import #import +#import +#import +#import +#import +#import +#import #pragma clang diagnostic pop @@ -26,9 +36,6 @@ class SkiaMetalSurfaceFactory { friend class IOSSkiaContext; public: - static sk_sp makeWindowedSurface(SkiaMetalContext *context, - id texture, int width, - int height); static sk_sp makeOffscreenSurface(id device, SkiaMetalContext *context, int width, int height); @@ -76,9 +83,16 @@ class IOSSkiaContext : public RNSkia::WindowContext { } // Get the texture from the drawable - _skSurface = SkiaMetalSurfaceFactory::makeWindowedSurface( - _context, _currentDrawable.texture, _layer.drawableSize.width, - _layer.drawableSize.height); + GrMtlTextureInfo fbInfo; + fbInfo.fTexture.retain((__bridge void *)_currentDrawable.texture); + + GrBackendRenderTarget backendRT = GrBackendRenderTargets::MakeMtl( + _layer.drawableSize.width, _layer.drawableSize.height, fbInfo); + + _skSurface = SkSurfaces::WrapBackendRenderTarget( + _context->skContext.get(), backendRT, kTopLeft_GrSurfaceOrigin, + kBGRA_8888_SkColorType, nullptr, nullptr); + return _skSurface; } @@ -95,9 +109,9 @@ class IOSSkiaContext : public RNSkia::WindowContext { void resize(int width, int height) override { _skSurface = nullptr; } - int getWidth() override { return _layer.frame.size.width; }; + int getWidth() override { return _layer.frame.size.width * _layer.contentsScale; }; - int getHeight() override { return _layer.frame.size.height; }; + int getHeight() override { return _layer.frame.size.height * _layer.contentsScale; }; private: SkiaMetalContext *_context; diff --git a/packages/skia/ios/RNSkia-iOS/SkiaMetalSurfaceFactory.mm b/packages/skia/ios/RNSkia-iOS/SkiaMetalSurfaceFactory.mm index e5652aaa81..3d4db6a193 100644 --- a/packages/skia/ios/RNSkia-iOS/SkiaMetalSurfaceFactory.mm +++ b/packages/skia/ios/RNSkia-iOS/SkiaMetalSurfaceFactory.mm @@ -46,26 +46,6 @@ return std::make_unique(context, texture, width, height); } -sk_sp SkiaMetalSurfaceFactory::makeWindowedSurface( - SkiaMetalContext *context, id texture, int width, int height) { - GrMtlTextureInfo fbInfo; - fbInfo.fTexture.retain((__bridge void *)texture); - - GrBackendRenderTarget backendRT = - GrBackendRenderTargets::MakeMtl(width, height, fbInfo); - - auto skSurface = SkSurfaces::WrapBackendRenderTarget( - context->skContext.get(), backendRT, kTopLeft_GrSurfaceOrigin, - kBGRA_8888_SkColorType, nullptr, nullptr); - - if (skSurface == nullptr || skSurface->getCanvas() == nullptr) { - RNSkia::RNSkLogger::logToConsole( - "Skia surface could not be created from parameters."); - return nullptr; - } - return skSurface; -} - sk_sp SkiaMetalSurfaceFactory::makeOffscreenSurface( id device, SkiaMetalContext *context, int width, int height) {