Как легко переключиться с 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
С учетом всего сказанного я время от времени вижу частичное совпадение мнений, но с гораздо более низкой частотой.