如何从MTKView无缝切换到UIView显示

时间:2018-07-13 19:20:58

标签: swift uiview synchronization metal metalkit

我有一个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。 在许多屏幕绘制中,我认为,这样可以减少View交换期间的帧丢失,但是我想要一个万无一失的万能解决方案。基本上,我需要的是仅在strokeUIView准备显示后才清除strokeViewMetal。任何指针将不胜感激

1 个答案:

答案 0 :(得分:0)

当我将MTKView的presentsWithTransaction属性设置为true时,99%的测试都解决了MTKView和UIView之间的同步问题。根据Apple的文档:

  

将此值设置为true会更改此默认行为,以便您   MTKView使用任何一种同步显示其可绘制内容   核心动画交易是当前可绘制对象的交易时间   present()方法被调用。

完成后,必须从以下位置修改绘制循环:

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

这样做是为了防止Core活动在我们准备展示MTKView的drawable之前结束。

所有这些设置之后,我可以简单地做到:

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

话虽如此,我确实时不时地看到视图的重叠,但是频率要低得多