金属有后备缓冲吗?

Does metal have a back buffer?

我目前正在追踪我的 Metal 应用程序中的一些视觉弹出,我相信这是因为我直接绘制到帧缓冲区,而不是后台缓冲区

  // this is when I've finished passing commands to the render buffer and issue the draw command.  I believe this sends all the images directly to the framebuffer instead of using a backbuffer
  [renderEncoder endEncoding];
  [mtlCommandBuffer presentDrawable:frameDrawable];
  [mtlCommandBuffer commit];
  [mtlCommandBuffer release];
  //[frameDrawable present];   // This line isn't needed (and I believe is performed by presentDrawable

后来谷歌了几次,我还没有找到任何关于金属后缓冲区的文档。我知道我可以自己滚动,但我无法相信金属不支持后台缓冲区。

这是我如何设置 CAMetalLayer 对象的代码片段。

+ (id)layerClass
{
    return [CAMetalLayer class];
}

- (void)initCommon
{
    self.opaque          = YES;
    self.backgroundColor = nil;
    ...
}

-(id <CAMetalDrawable>)getMetalLayer
{
    id <CAMetalDrawable> frameDrawable;
    while (!frameDrawable && !frameDrawable.texture)
    {
        frameDrawable = [self->_metalLayer nextDrawable];
    }
    return frameDrawable;
}

我可以在我的 CAMetalLayer 对象上启用后缓冲,还是我需要自己滚动?

我假设 back-buffer,你的意思是渲染到一个渲染缓冲区,而相应的 front-buffer显示?

在 Metal 中,概念是由您从 CAMetalLayer 中提取的可绘制对象提供的。 CAMetalLayer 实例维护一个小型可绘制对象池(通常为 3 个),每次调用 nextDrawable 时从池中检索其中一个,并在您调用 returns 之后将其返回到池中调用 presentDrawable 并在渲染完成后(可能需要一段时间,因为 GPU 从 CPU 异步运行)。

实际上,在每个帧循环中,您通过调用 nextDrawable 获取一个 back-buffer,并使其有资格成为 front- buffer 通过调用 presentDrawable: 并提交 MTLCommandBuffer.

由于池中只有 3 个可绘制对象,问题是您必须自己管理此生命周期,方法是在调用 nextDrawable 时添加适当的 CPU 资源同步,并在渲染完成后获得的回调(根据 MTLCommandBuffer addCompletedHandler: 回调设置)。

通常您为此使用 dispatch_semaphore_t

_resource_semaphore = dispatch_semaphore_create(3);

然后在调用 nextDrawable 之前输入以下内容:

dispatch_semaphore_wait(_resource_semaphore, DISPATCH_TIME_FOREVER);

并且在您的 addCompletedHandler: 回调处理程序中:

dispatch_semaphore_signal(_resource_semaphore);

查看 Apple 提供的一些简单的 Metal 示例应用程序,了解实际效果。关于这方面的 Apple 文档并不多。