4

我目前正在跟踪我的 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 对象上启用后缓冲区,还是需要自己滚动?

4

1 回答 1

9

我假设back-buffer是指正在渲染的渲染缓冲区,而相应的前缓冲区正在显示?

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

实际上,在每个帧循环中,您通过调用 来获取一个后缓冲区nextDrawable并通过调用和提交.presentDrawable:MTLCommandBuffer

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

通常,您dispatch_semaphore_t为此使用 a:

_resource_semaphore = dispatch_semaphore_create(3);

然后在调用之前添加以下内容nextDrawable

dispatch_semaphore_wait(_resource_semaphore, DISPATCH_TIME_FOREVER);

这在你的addCompletedHandler:回调处理程序中:

dispatch_semaphore_signal(_resource_semaphore);

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

于 2015-08-14T18:36:45.853 回答