artem
artem

Reputation: 16798

Skia memory issues when used from static library on iOS

I've compiled Skia for iOS:

bin/gn gen out/ios-apple --args='target_os="ios" target_cpu="arm64" ios_use_simulator=false skia_enable_tools=false is_official_build=false is_debug=true is_trivial_abi=false skia_use_metal=true skia_use_expat=false skia_use_system_expat=false skia_use_system_libpng=false skia_use_system_libwebp=false skia_use_system_zlib=false skia_use_system_freetype2=false skia_use_system_harfbuzz=false skia_use_system_icu=false skia_enable_gpu=true skia_enable_skottie=false skia_compile_modules=true extra_cflags=["-F/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library/Frameworks"] extra_ldflags=["-framework", "CoreFoundation", "-framework", "Metal"]'

This is how I'm using it in a View Controller:

#import <MetalKit/MetalKit.h>
#import <Metal/Metal.h>
#import <UIKit/UIKit.h>

#define SK_GANESH
#define SK_METAL

#import <include/gpu/ganesh/GrDirectContext.h>
#import <include/core/SkSurface.h>

@interface SkiaViewController : UIViewController <MTKViewDelegate>

@property (nonatomic, strong) MTKView *mtkView;
@property (nonatomic, strong) id<MTLDevice> metalDevice;
@property (nonatomic, strong) id<MTLCommandQueue> metalQueue;

@property (nonatomic, assign) sk_sp<GrDirectContext> grDirectContext;
@property (nonatomic, assign) sk_sp<SkSurface> surface;
@end
#import <MetalKit/MetalKit.h>
#import <Metal/Metal.h>

#define SK_GANESH
#define SK_METAL

#import "include/gpu/ganesh/GrTypes.h"
#import "include/gpu/ganesh/SkSurfaceGanesh.h"
#import "include/gpu/ganesh/mtl/GrMtlTypes.h"

#import <include/gpu/ganesh/GrBackendSurface.h>
#import <include/gpu/ganesh/SkSurfaceGanesh.h>
#import <include/gpu/ganesh/mtl/GrMtlBackendContext.h>
#import <include/gpu/ganesh/mtl/GrMtlBackendSurface.h>
#import <include/gpu/ganesh/mtl/GrMtlDirectContext.h>
#import <include/gpu/ganesh/mtl/SkSurfaceMetal.h>

#import <include/gpu/ganesh/GrDirectContext.h>
#import <include/core/SkSurface.h>
#import <include/core/SkCanvas.h>
#import <include/core/SkColorSpace.h>

#import "SkiaViewController.h"

@implementation SkiaViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
#ifndef SK_GANESH
    NSLog(@"SK_GANESH is undefined");
#endif
    
#ifndef SK_METAL
    NSLog(@"SK_METAL is undefined");
#endif
    
    [self setMetalDevice:MTLCreateSystemDefaultDevice()];
    [self setMetalQueue:[[self metalDevice] newCommandQueue]];
    
    if(![self metalDevice]) {
        NSLog(@"Metal is not supported on this device");
        return;
    }
    
    if(![self metalQueue]) {
        NSLog(@"Failed to create Metal command queue");
        return;
    }
    
    // Initialize MTKView
    self.mtkView = [[MTKView alloc] initWithFrame:self.view.bounds device:self.metalDevice];
    self.mtkView.delegate = self;
    self.mtkView.enableSetNeedsDisplay = YES;
    
    [self.mtkView setDepthStencilPixelFormat:MTLPixelFormatDepth32Float_Stencil8];
    [self.mtkView setColorPixelFormat:MTLPixelFormatBGRA8Unorm];
    [self.mtkView setSampleCount:1];
    
    NSLog(@"self.metalDevice.maxBufferLength=%lu", self.metalDevice.maxBufferLength);
    
    self.mtkView.layer.borderWidth = 2.0; // Set border width
    self.mtkView.layer.borderColor = [UIColor redColor].CGColor; // Set border color
    
    [self.view addSubview:self.mtkView];
    
    // Initialize Skia with Metal
    GrMtlBackendContext backendContext = {};
    backendContext.fDevice.retain((__bridge void*)[self metalDevice]); // also tried __bridge_retained
    backendContext.fQueue.retain((__bridge void*)[self metalQueue]);
    
    GrContextOptions grContextOptions;
    
    self.grDirectContext = GrDirectContexts::MakeMetal(backendContext, grContextOptions);
    
    if (![self grDirectContext]) {
        NSLog(@"Failed to create GrDirectContext");
        return;
    }
    
    NSLog(@"Created GrDirectContext");
}

#pragma mark - MTKViewDelegate

- (void)drawInMTKView:(nonnull MTKView *)view {
}

- (void)mtkView:(nonnull MTKView *)view drawableSizeWillChange:(CGSize)size {
    
}

@end

In this case it works fine.

But if I create a static library inside the same project, move ViewController into that static library and use view controller from the static library in my app, I'm facing memory issues in GrDirectContexts::MakeMetal.

Sometimes it crashes with bad access error, sometimes some of pointers are becoming nullptr, for example in backendContext right after setting these values.

Same if I move this Skia initialization in a separate C++ library (compiled by CMake, not in Xcode directly).

I guess that this is some issue with Skia's smart pointers (maybe something is stripped when linking with static lib?), but I'm not familiar with Obj-C development and interop with C++ for iOS.

UPD. I've tested with a simple C++ library without passing any Obj-C pointers to Skia, and can confirm that I have exactly the same issues with it — at some point a pointer inside an sk_sp becomes invalid (for example, when Skia tries to free it).

What may be wrong here?

Upvotes: 1

Views: 60

Answers (0)

Related Questions