2016-10-16 1 views
2

화면이 끊어지지 않고 디스플레이의 재생 빈도로 부드럽게 움직이는 애니메이션을 얻으려고합니다. 애니메이션은 Metal을 사용하여 렌더링됩니다. 애플이 당신에게 이것을 위해 CVDisplayLink 기반의 타이머를 사용하라고 말한 것을 이해한다면, 그것이 내가 한 일이다.배터리 전원이 켜져있을 때 CVDisplayLink 타이머의 안정도

전원 어댑터에 연결하면 모든 것이 데스크톱 컴퓨터와 랩톱에서 정상적으로 작동합니다. 그러나 랩톱이 배터리로 작동 할 때, 특히 배터리가 가득차 있지 않은 경우 애니메이션에서 매우 눈에 띄는 끊김 현상을 볼 수 있습니다. 그래도 눈물은 없습니다. 모든 화면을 새로 고침 할 때 타이머가 실행되지 않는 것 같습니다.

나는 CPU가 줄어들 기 때문에 이것이 아니라고 확신한다. CPU 사용률이 10 % 미만이고 애니메이션이 계산 및 렌더링에 2ms 미만 소요됩니다. 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에 타이머가 모든 화면을 새로 고침 할 때마다 실행되도록 보장 할 수 있습니까? 이것이 금속 문제입니까? 배터리로 잘 돌아가는 게임과 화면 보호기를 보았지만 OpenGL을 사용한다고 가정합니다.

답변

1

코드를 올바르게 읽는다면 변경 될 수없는 간격으로 CVDisplayLink이 호출된다고 가정합니다. 그것은 전혀 약속하지 않았습니다. 시스템은 새로 고침 간격이나 드롭 프레임을 자유롭게 수정할 수 있습니다. 모든 실시간 시스템에는 프레임을 삭제하는 기능이 있어야합니다. 그것이 "실시간"이라는 것이 의미하는 것의 핵심입니다.

"현재 표시된 시간"과 "대상 출력"시간이 전달되었습니다. 목표 출력을위한 올바른 프레임을 계산하기 위해 그것들을 사용해야합니다. 코드에서 출력 시간을 사용하는 것을 보지 못합니다.

+0

감사합니다. 나는 여러분이 작성한 것을 이해하고, 'CACurrentMediaTime'으로 검색 한 경과 시간에 애니메이션을 기반으로한다고하더라도 콜백에 대한 인수로 전달 된 시간을 사용하면 차이가 있는지 여부를 확인하려고 노력할 것입니다. 즉, 내 진짜 질문은 내 코드가 충분히 빠르며 시스템이 그렇지 않으면 부하가 많이 걸리지 않는 한 "프레임을 건너 뛰지"않는 타이머를 얻고 자 할 때 취해야 할 접근 방식입니다. 게임 개발자는이 작업을 수행 할 수있는 방법이 있어야합니다. 그렇지 않으면 게임에서도 배터리가 누락 될 수 있습니다. –

+0

시스템이 절전을 위해 프레임을 버릴 수 있습니다. 저는 시스템이 저전력 모드로 전환되지 않도록 요청할 수있는 전원 단언을 할 수 있다고 믿습니다. 그러나 배터리를 훨씬 더 빠르게 태울 것이므로 실제로는 이걸 가져야 만하지 않는 한 까다 롭습니다. 일반적으로 출력 시간 (현재 시간 아님)을 사용하는 경우 부드럽게 처리해야합니다. https://developer.apple.com/videos/play/wwdc2012/711/ –

+0

'CACurrentMediaTime'을 사용하는 경우에도 솔직히 말더듬을 재현 할 수 없습니다. 어쨌든, 답안에서 제안 된대로 콜백에 전달 된 출력 시간을 사용하면 개선 된 것이므로 지금 구현했습니다. 그래서 나는 이것을 올바른 대답으로 받아 들일 것입니다. –

관련 문제