CAMetalLayer nextDrawable内存泄漏?

时间:2019-12-21 22:36:09

标签: ios objective-c memory-leaks

我目前正在调查iOS中的内存泄漏。

我们有一个ViewController和该Controller的视图。
当前已反复推送和弹出ViewController(出于调试目的)。
该视图包含一个CAMetalLayer(类方法layerClass返回CAMetalLayer)和一个CADisplayLink,后者调用我的render方法。
当我第一次调用[metalLayer nextDrawable]时,该应用程序分配了大约20MB。 但是,当ViewController弹出时,只有一小部分被释放! 我100%确定我没有保留周期或任何东西。

这是我的渲染初始化代码:

-(void)initializeRendering {
@autoreleasepool {
    id<MTLDevice> device = [[MetalRenderingSession sharedInstance] renderDevice];
    [self setCommandQueue:[device newCommandQueue]];
    CAMetalLayer* layer = static_cast<CAMetalLayer*>([self layer]);
    layer.device = device;
    layer.pixelFormat = MTLPixelFormatRGBA16Float;
    layer.framebufferOnly = true;
    layer.maximumDrawableCount = 2;
    layer.contentsScale = [self contentScaleFactor];
    [self setMetalLayer:layer];
    CGSize screenSize = [[UIScreen mainScreen] bounds].size;
    MTLTextureDescriptor* depthTextureDescriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatDepth32Float
        width:static_cast<NSUInteger>(screenSize.width) height:static_cast<NSUInteger>(screenSize.height) mipmapped:NO];
    [depthTextureDescriptor setUsage:MTLTextureUsageRenderTarget];
    id<MTLTexture> depthTexture = [device newTextureWithDescriptor:depthTextureDescriptor];
    [self setTextureDepth:depthTexture];
    [self updateOrientation:[[UIApplication sharedApplication] statusBarOrientation] size:[self frame].size];
    CADisplayLink* renderLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(render)];
    [renderLink setPreferredFramesPerSecond:30];
    [self setDisplayLink:renderLink];
    [renderLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
}
}

这是我的实际渲染代码:

-(void)render {
@autoreleasepool {
    dispatch_semaphore_wait([self renderCommandExecuting], DISPATCH_TIME_FOREVER);
    id<MTLCommandBuffer> commandBuffer = [[self commandQueue] commandBuffer];
    [[self commandQueue] insertDebugCaptureBoundary];

    //commenting next line and lines that use drawable makes memory leak disappear?
    id<CAMetalDrawable> drawable = [[self metalLayer] nextDrawable];
    id<MTLRenderCommandEncoder> encoder = [self createCommandEncoderfromCommandBuffer:commandBuffer andDrawable:drawable];
    //creating ViewPort here
    [encoder setViewport:viewport];

    //doing rendering here, but for debugging purpoeses i disabled rendering 
    [encoder endEncoding];
    [commandBuffer presentDrawable:drawable];

    [commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> o) {
        dispatch_semaphore_signal([self renderCommandExecuting]);
    }];
    [commandBuffer commit];
    [commandBuffer waitUntilCompleted];
}
}

enter image description here

在我看来,对于每个CAMetalLayer,该应用都会创建一个IOSurface ,但是如何释放这些?

该图是步进式的,因为我等待2秒钟才弹出视图控制器。 当我按下视图控制器时,将出现“步骤”。
我注意到只有“ VM:IOSurface”爬升,其余的保持不变。

这是我的清理代码(在视图中,从viewWillDisappear调用):

-(void)stop {
[[self displayLink] setPaused:YES];
[[self displayLink] removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
//those are 4*4 float arrays, they are allocated in the view's init
free([self projectionMatrix]);
free([self viewMatrix]);
free([self modelMatrix]);
[self setCommandQueue:nil];
[self setMetalLayer:nil];
[self setTextureDepth:nil];
[self setRenderCommandExecuting:nil];
}

1 个答案:

答案 0 :(得分:0)

问题是<button id="btn1" onclick="kfunc('id1')">Küche</button> <button id="btn2" onclick="kfunc('id2')">Bad</button> <button id="btn3" onclick="kfunc('id3')">Wohnzimmer</button> <button id="btn4" onclick="kfunc('id4')">Melina</button> <button id="btn5" onclick="kfunc('id5')">Kleines Bad</button> <button id="btn6" onclick="kfunc('id6')">Schlafzimmer</button> <!-- Küche --> <div class="frame_kueche" id="id1"> <div class="buttons_close"> <button onclick="closefunc('id1')">X</button> </div> <button onclick="testfunc()">ab</button> </div> <!-- Bad --> <div class="frame_bad" id="id2"> <div class="buttons_close"> <button onclick="closefunc('id2')">X</button> </div> <button onclick="testfunc()">a</button> </div> <!-- Wohnzimmer --> <div class="frame_wohnzimmer" id="id3"> <div class="buttons_close"> <button onclick="closefunc('id3')">X</button> </div> <button onclick="testfunc()">a</button> </div> <!-- Melina --> <div class="frame_melina" id="id4"> <div class="buttons_close"> <button onclick="closefunc('id4')">X</button> </div> <button onclick="testfunc()">a</button> </div> <!-- kleines Bad --> <div class="frame_kleines_bad" id="id5"> <div class="buttons_close"> <button onclick="closefunc('id5')">X</button> </div> <button onclick="testfunc()">a</button> </div> <!-- Schlafzimmer --> <div class="frame_schlafzimmer" id="id6"> <div class="buttons_close"> <button onclick="closefunc('id6')">X</button> </div> <button onclick="testfunc()">a</button> </div>
您需要使用CADisplayLink才能正确释放它。 仅仅从RunLoop中删除它是不够的。