1

我有一个 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。在许多屏幕绘制中,我认为这会导致视图交换期间的丢帧更少,但我想要一个没有丢帧的万无一失的解决方案。基本上我所追求的是只有在 strokeUIView 准备好显示时才清除 strokeViewMetal 。任何指针将不胜感激

4

1 回答 1

1

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

将此值设置为 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

这样做是为了防止核心活动在我们准备好呈现 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

说了这么多,我确实时不时地看到视图重叠,但频率要低得多

于 2019-04-13T03:00:47.210 回答