CAMetalLayer 初始化仅适用于主线程

问题描述 投票:0回答:1

我确实有一个直接的 CAMetalLayer 设置,除了 CAMetalLayer 是在全局线程上初始化的,如下所示(调用 init,设置基本属性并添加为子层):

DispatchQueue.global().async {
    let renderLayer = CAMetalLayer()
    renderLayer.isOpaque = false
    renderLayer.frame = frame
    renderLayer.drawableSize = drawableSize
    renderLayer.framebufferOnly = false
    renderLayer.device = metalDevice
    renderLayer.pixelFormat = metalPixelFormat
    renderLayer.contentsScale = contentScale
    DispatchQueue.main.async {
        view.layer.addSublayer(renderLayer)
    }
}

此代码运行时没有任何运行时错误,但不幸的是,当渲染到

CAMetalLayer
可绘制对象时,屏幕上没有显示渲染输出。测试表明,
CAMetalLayer
可绘制对象确实具有适当的纹理(具有所需的大小),并且数据按预期写入其中,但未显示在屏幕上。

令我惊讶的是,在主线程上运行

CAMetalLayer
初始化修复了这个问题。所以解决办法如下:

DispatchQueue.global().async {
    var renderLayer: CAMetalLayer!
    DispatchQueue.main.sync {
        renderLayer = CAMetalLayer()
    }
    renderLayer.isOpaque = false
    renderLayer.frame = frame
    renderLayer.drawableSize = drawableSize
    renderLayer.framebufferOnly = false
    renderLayer.device = metalDevice
    renderLayer.pixelFormat = metalPixelFormat
    renderLayer.contentsScale = contentScale
    DispatchQueue.main.async {
        view.layer.addSublayer(renderLayer)
    }
}

因为我希望能够完全在后台线程上运行

CAMetalLayer
创建,所以我想避免在主线程上调用
CAMetalLayer()
。另外,我在文档中找不到在主线程上初始化
CAMetalLayer
的任何要求。

所以我的问题是:

  • 是否可以在后台线程上运行 init
    CAMetalLayer()
    ,如果可以的话如何运行?
  • 如果不可能:为什么?

其他信息:我正在使用 XCode 11 并在 iOS 13.1 上运行代码。我在 XCode 10 和 iOS 版本 12 上也遇到了同样的问题。

swift multithreading metal
1个回答
0
投票

-[CAMetalLayer init]
需要在 CA 渲染器循环上注册观察者并接收回调以完成初始化。但是,使用
DispatchQueue.global()
意味着无法保证何时调用回调,从而导致 CAMetalLayer 等待并阻止任何绘图发生。如果您需要在后台线程上初始化 CAMetalLayer,请改用 NSThread。

__block CAMetalLayer *metalLayer = [CAMetalLayer new];;
dispatch_semaphore_t s = dispatch_semaphore_create(0);
NSThread *t = [[NSThread alloc] initWithBlock:^{
    metalLayer = [CAMetalLayer new];
    dispatch_semaphore_signal(s);
}];
[t start];
dispatch_semaphore_wait(s, DISPATCH_TIME_FOREVER);
dispatch_release(s);
[t release];
© www.soinside.com 2019 - 2024. All rights reserved.