代码之家  ›  专栏  ›  技术社区  ›  zzyzy

“nextDrawable”非常难以捉摸的金属问题

  •  0
  • zzyzy  · 技术社区  · 6 年前

    我有四个1920x1080的装置 MTKView 实例作为 NSWindow 在3840x2160监视器上作为调试配置。想象一下,我的四个视图被编号为象限(右上角的“1”,然后逆时针)。在这些视图上播放了四个视频。他们的 CVPixelBuffers 从各自的 AVPlayer ,通过 CVDisplayLink 为每个渲染循环。每个 由这四个配置为手动绘制 CVDisplayLink公司 回拨。这个 draw 呼叫在一个 @autoreleasepool .

    所有这一切在95%的时间内都能很好地工作——在Radeon R9 M395 iMac 5k 2015年末w/Fusion驱动器上,大约75%的GPU内存使用率和20%的GPU处理率。Xcode中的金属跟踪使我的所有GPU渲染每帧不超过5毫秒。

    我想找出为什么我的一些视频有5%的时间会结巴。

    在每个 MTKView公司 drawRect 调用,我对已分配的纹理执行4次内核着色器操作,最多两次传入 CVPixelBuffer 纹理(即从一个视频淡入下一个视频)。我不要求也不碰 currentRenderPassDescriptor 在里面。

    MTLComputeCommandEncoder 工作,我有一张最后的通行证 MTLRenderCommandEncoder 以及一组以最终计算纹理结果作为输入的顶点:

    - (void)drawRect:(NSRect)dirtyRect {
        [super drawRect:dirtyRect];
        dispatch_semaphore_wait(self.inflightSemaphore, DISPATCH_TIME_FOREVER);
        id<MTLCommandBuffer> commandBuffer = [metalCommandQueue commandBuffer];
    
        <do 4 passes of compute work>
    
        // ********* The next line is where WARNINGS (see below) occur ***********
        MTLRenderPassDescriptor *renderPassDescriptor = self.currentRenderPassDescriptor;
    
        id<MTLDrawable> currentDrawable = nil;
        if (renderPassDescriptor) {
           currentDrawable = self.currentDrawable;
           [self doVertexWork:inputTexture
              onCommandBuffer:commandBuffer
               withDescriptor:renderPassDescriptor];
        }
    
        [commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> buffer) {
            dispatch_semaphore_signal(self.inflightSemaphore);
        }];
    
        if (currentDrawable)
            [commandBuffer presentDrawable:currentDrawable];
        [commandBuffer commit];
    
        commandBuffer=nil;
    }
    


    如果我做一个GPU帧捕获,我注意到帧速率为120fps,4个绘制调用,4个命令缓冲区,4个渲染编码器。但是,在显示的行上,我总共收到7个警告:

    • CAMetalLayer nextDrawable Called Early (一次)
    • CAMetalLayer nextDrawable was Called Unnecessarily (三次)
    • Command Buffer was not Enqueued and Committed in this Frame

    顺便说一下,Xcode提供了一个关于提前调用的说明: "Your application called CAMetalLayer nextDrawable earlier than needed. This may block execution until a CAMetalDrawable is available. Delay the call to nextDrawable until the drawing is needed for encoding".

    我注意到在文档中,阻塞的执行发生了一秒钟,这与我偶尔看到的口吃的时间相匹配(即每1秒左右更新一次)。

    endEncoding 当我做顶点运算时,我得到一个 "CAMetalDrawable used from Earlier Frame" 警告(三次,仅使用象限1、2、4中的纹理)。

    我无法真正弄清楚我的问题是什么,因为我正在遵循我所看到的所有示例所使用的技术。


    更新#1

    基于 Ken-Thomases

    [metalCommandQueue insertDebugCaptureBoundary];
    

    这几乎解决了所有声称的问题,但我仍然偶尔看到1秒口吃。唯一剩下的问题是 带有“您的应用程序调用 CAMetalLayer nextDrawable 但没有使用返回的 CAMetalDrawable

    据我所知,这个 nextDrawable


    0 回复  |  直到 6 年前