我有四个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>
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