Инициализация CAMetalLayer работает только в основном потоке - PullRequest
2 голосов
/ 11 октября 2019

У меня есть прямая настройка 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.

...