我试图让动画在没有屏幕撕裂的情况下以显示器的刷新率顺利运行。动画使用Metal渲染。据我所知,Apple告诉您使用基于CVDisplayLink的计时器,这就是我所做的。
当桌面计算机和笔记本电脑连接到电源适配器时,一切正常。然而,当笔记本电脑使用电池运行时,特别是当电池电量不足时,我可以看到动画中非常明显的卡顿。但是,没有撕裂。似乎每次刷新屏幕都不会触发计时器。
我很确定这不是因为CPU受到限制。 CPU利用率低于10%,动画计算和渲染时间不到2毫秒;在60Hz时,它将有16ms的速度。
为了它的价值,这就是我设置计时器的方式:
private func makeDisplayLink(window: NSWindow) -> CVDisplayLink
{
func displayLinkOutputCallback(_ displayLink: CVDisplayLink, _ inNow: UnsafePointer<CVTimeStamp>, _ inOutputTime: UnsafePointer<CVTimeStamp>, _ flagsIn: CVOptionFlags, _ flagsOut: UnsafeMutablePointer<CVOptionFlags>, _ displayLinkContext: UnsafeMutableRawPointer?) -> CVReturn {
unsafeBitCast(displayLinkContext, to: MetalScreenSaverView.self).animateOneFrame()
return kCVReturnSuccess
}
var link: CVDisplayLink?
let screensID = UInt32(window.screen!.deviceDescription["NSScreenNumber"] as! Int)
CVDisplayLinkCreateWithCGDisplay(screensID, &link)
CVDisplayLinkSetOutputCallback(link!, displayLinkOutputCallback, UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque()))
return link!
}
稍后我通过以链接作为参数调用CVDisplayLinkStart
来启动链接。如果您感兴趣,可以在https://github.com/thoughtworks/dancing-glyphs/blob/master/Library/MetalScreenSaverView.swift
有什么想法吗?我可以告诉OS X以确保在每次屏幕刷新时触发计时器吗?这是Metal的问题吗?我已经看到游戏和屏幕保护程序在电池上运行良好,但我假设使用OpenGL。
答案 0 :(得分:1)
如果我正确阅读您的代码,您可以假设CVDisplayLink
在某个不可更改的时间间隔内被调用。根本没有承诺。系统完全可以自由修改刷新间隔或丢帧。所有实时系统必须包括丢帧的能力。这就是&#34;实时的核心所在。&#34;
您已通过当前显示的&#34;&#34;时间和&#34;目标输出&#34;时间。您应该使用它们来计算目标输出的正确帧。我没有看到你在代码中使用输出时间。