Как легко переключиться с MTKView на UIView?

У меня есть MTKView, содержимое которого я рисую в UIView. Я хочу поменять отображение с MTKView на UIView без заметных изменений. Как добиться?

В настоящее время у меня есть

let strokeCIImage = CIImage(mtlTexture: metalTextureComposite...) // get MTLTexture
let imageCropCG = cicontext.createCGImage(strokeCIImage...) // convert to CGImage
let layerStroke = CALayer() // create layer
layerStroke.contents = imageCropCG // populate with CGImage
strokeUIView.layer.addSublayer(layerStroke)  // add to view
strokeUIView.layerWillDraw(layerStroke) //heads up to strokeUIView

и метод делегата в layerWillDraw(), который очищает MTKView.

strokeViewMetal.metalClearDisplay()

В результате я часто вижу падение кадра, в котором ничего не отображается.

В надежде на четкое разделение двух задач я также попробовал следующее:

let dispatchWorkItem = DispatchWorkItem{
      print("lyr add start")
      self.pageCanvasImage.layer.addSublayer(sublayer)
      print("lyr add end")
 }

let dg = DispatchGroup()

DispatchQueue.main.async(group: dg, execute: dispatchWorkItem)
//print message when all blocks in the group finish
dg.notify(queue: DispatchQueue.main) {
   print("dispatch mtl clear")
   self.strokeCanvasMetal.setNeedsDisplay()  // clear MTKView
}

Идея заключается в том, чтобы добавить новый CALayer в UIImageView, а затем очистить MTKView. Я думаю, что на многих рисунках экрана это приводит к уменьшению количества кадров при смене режима просмотра, но я бы хотел надежное решение без капель. По сути, я собираюсь очистить strokeViewMetal только после того, как strokeUIView готов к отображению. Любые указатели будут оценены

0 ответов

Проблемы с синхронностью между MTKView и UIView решаются для 99% моих тестов, когда я устанавливаю MTKView presentsWithTransaction свойство к истине. Согласно документации Apple:

Установка этого значения в true изменяет это поведение по умолчанию, так что ваш MTKView отображает свой рисуемый контент синхронно, используя ту транзакцию Core Animation, которая является текущей в момент вызова метода draw () ().

Как только это будет сделано, цикл рисования должен быть изменен с:

commandEncoder.endEncoding()  
commandBuffer.present(drawable)  
commandBuffer.commit()

чтобы:

commandEncoder.endEncoding()  
commandBuffer.commit()  
commandBuffer.waitUntilScheduled()  // synchronously wait until the drawable is ready
drawable.present() // call the drawable’s present() method directly

Это сделано для того, чтобы предотвратить завершение основной деятельности до того, как мы будем готовы представить MTKView для рисования.

Со всем этим я могу просто:

let strokeCIImage = CIImage(mtlTexture: metalTextureComposite...) // get MTLTexture
let imageCropCG = cicontext.createCGImage(strokeCIImage...) // convert to CGImage
let layerStroke = CALayer() // create layer
layerStroke.contents = imageCropCG // populate with CGImage
// the last two events will happen synchronously
strokeUIView.layer.addSublayer(layerStroke)  // add to view
strokeViewMetal.metalClearDisplay() // empty out MTKView

С учетом всего сказанного я время от времени вижу частичное совпадение мнений, но с гораздо более низкой частотой.

Другие вопросы по тегам