Smoothness of animation interval
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 9.7k
- Forks
- 565
- PR merge metrics
- No merged PRs in 30d
Description
This issue is to track a potential improvement for later. The current state of computing the interval passed to animations is "good enough".
Currently, the code for computing the animation interval is based on the elapsed wall clock time between calls to the window `paint` method. This should be pretty close to the reciprocal of the frame rate, but is potentially subject to jitter, especially if there are handlers in the event loop that take a nontrivial amount of time to run.
The [comment on the `Widget::anim` method](https://github.com/xi-editor/druid/blob/5a25750697513cc1b63aa34b9b3d1332f9350787/src/widget/mod.rs#L126) reads:
> The `interval` argument is the time in nanoseconds between frames, for the purpose of computing animations. When framerate is steady, it should be exactly the reciprocal of the refresh rate of the monitor. If we are skipping frames, its cumulative sum should approximately track the passage of wall clock time and otherwise should be chosen to optimize for smoothness of animations.
>
> The ideal heuristic for computing this interval is a deep topic, ideally the subject of a blog post when I figure it out.
(This comment will be blown away by the merge of the muggle branch, which is one reason I'm capturing it in an issue.)
My current thinking is that a good definition for the interval is the best guess of the presentation time for the next frame relative to the previous one. When this guess is accurate, the animation will be perceived as smooth. As stated in the above quote, when we're not skipping frames, it's not really necessary to "guess," it should be possible to get an accurate value from the graphics adapter.
What to do when we are skipping frames? One solution is to query presentation statistics (possibly [GetFrameStatistics method](https://docs.microsoft.com/en-us/windows/win32/api/dxgi/nf-dxgi-idxgiswapchain-getframestatistics) on Windows or [CVDisplayLink](https://developer.apple.com/documentation/corevideo/cvdisplaylink) on mac) and do some kind of moving average of past frame-to-frame intervals.
It might be possible to estimate the likelihood of a dropped frame by looking at the wall-clock time and/or presentation statistics at the time the interval is computed. Figuring out a good heuristic will no doubt require some empirical measurement.
Another intriguing possibility to explore is to deliberately throttle the frame rate to make it consistent. For example, if it takes about 17ms to display a frame, it might better to present consistently at 30fps than to do it mostly at 60fps but with periodic frame drops. On Windows, this can be done fairly easily by setting `SyncInterval` to a value other than 1 in the [IDXGISwapChain::Present](https://docs.microsoft.com/en-us/windows/win32/api/dxgi/nf-dxgi-idxgiswapchain-present) method.
Likely more research is needed to figure out the absolute best way to do this, which again is a reason I'm filing an issue rather than just digging into it.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the Widget::anim comment in src/widget/mod.rs and trace how the animation interval is currently computed from window paint calls. Compare the possible presentation-statistics approaches named in the issue, including DXGI GetFrameStatistics and CVDisplayLink. Done would require an empirically supported heuristic for smooth intervals, but the issue does not define a specific implementation or test.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- desktop, performance
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 15/100