为什么WPF中的帧频不规则且不受监控刷新的限制? [英] Why is Frame Rate in WPF Irregular and Not Limited To Monitor Refresh?

查看:231
本文介绍了为什么WPF中的帧频不规则且不受监控刷新的限制?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用简单的WPF动画测量帧之间的时间。 Perforator表示,该应用的性能约为60fps,因此我希望帧之间的时间约为16.6ms,几乎没有偏差。

I'm measuring the time between frames in a simple WPF animation. Perforator says the app performs at ~60fps, so I expected the time between frames to be ~16.6ms with little deviation.

    public MainWindow()
    {
    ...
        CompositionTarget.Rendering += Rendering;
    }

    List<long> FrameDurations = new List<long>();
    private long PreviousFrameTime = 0;
    private void Rendering(object o, EventArgs args)
    {
        FrameDurations.Add(DateTime.Now.Ticks - PreviousFrameTime);
        PreviousFrameTime = DateTime.Now.Ticks;
    }

两件事让我感到惊讶:


  • 帧之间的时间是相当不规则的

  • 帧之间的时间是〜8ms。我曾期望监视器的刷新率将设置帧之间的时间下限(即,每帧之间60Hz = 16.6ms,更快的速度毫无意义)。

Y-帧之间的时间间隔(滴答声)(10,000滴= 1ms)

X-帧数

Y - Time between frames in ticks (10,000 ticks = 1ms)
X - Frame count

可能的混杂因素


  • 计时器不准确

  • 如果CompositionTarget.Rendering实际上与单个帧的绘制无关

我正在使用的项目: SimpleWindow.zip

===编辑

Markus指出我可以使用RenderingEventArgs.RenderingTime.Ticks代替DateTime.Now.Ticks。我重复运行,得到了截然不同的结果。唯一的区别是计时方法:

Markus pointed out I could be using RenderingEventArgs.RenderingTime.Ticks instead of DateTime.Now.Ticks. I repeated the run and got very different results. The only difference is timing method:

DateTime.Now.Ticks

< img src = https://i.stack.imgur.com/A0ek3.png alt = DefaultFrameRate>

RenderingEventArgs.RenderingTime.Ticks

来自RenderingEventArgs的数据产生的数据更接近预期的16.6ms /帧,并且是一致的。

Data from RenderingEventArgs produced data much closer the expected 16.6ms/frame, and it is consistent.


  • 我不确定为什么DateTime.Now和RenderingEventArgs会产生如此完全不同的数据。

  • 假设RenderingEventArgs产生正确的时间,仍然有些令人不安的是,这些时间不是预期的16.6毫秒。

WPF每16.6ms更新一次,而WPF每14.9ms更新一次,我们可以预期会导致竞争的竞争状况。也就是说,在显示器尝试读取图像时,WPF大约每隔10帧就会尝试写入其图像。

If the display is updating every 16.6ms and WPF is updating every 14.9ms, we can expect a race condition that would result in tearing. That is to say, roughly every 10th frame WPF will be trying to write its image while the display is trying to read the image.

推荐答案

我向WPF团队提出了这个问题,这是我得到的答复的摘要:

I raised this question with the WPF team and here is a summary of the response I was given:


从UI计算帧率
线程很困难。 WPF将
的UI线程与渲染线程解耦。
UI线程将渲染:

Calculating the framerate from the UI thread is difficult. WPF decouples the UI thread from the render thread. The UI thread will render:


  • 每当有东西被标记为脏东西时,我们便开始渲染
    优先。
    的发生频率可能​​比刷新率高。

  • Whenever something is marked as dirty and we drain down to Render priority. This can happen more often than the refresh rate.

如果动画正在处理中(或者有人钩了
CompositionTarget。事件),我们
将在呈现线程中的每个
之后呈现在UI线程上。
这涉及提前定时
树,以便动画计算其新的
值。

If an animation is pending (or if someone hooked the CompositionTarget.Rendering event) we will render on the UI thread after every present from the render thread. This involves advancing the timing tree so animations calculate their new values.

因此,
CompositionTarget.Rendering事件可以在每个帧中多次引发

我们在RenderingEventArgs中以
报告预期的帧时间,并且当报告的
帧时间发生变化时,
应用程序仅应执行
每帧工作。

Because of this, the CompositionTarget.Rendering event can be raised multiple times per "frame". We report the intended "frame time" in the RenderingEventArgs, and applications should only do "per-frame" work when the reported frame time changes.

请注意,UI线程正在执行许多
的事情,因此,假设承担CompositionTarget.Rendering
事件处理程序的情况下,
并不可靠以可靠的
节奏运行。我们使用的模型(将两个线程的
解耦)意味着UI
线程可能会落后一点,因为
会在
的未来帧时间内计算动画。

Note that the UI thread is doing many things, so it is not reliable to assume the CompositionTarget.Rendering event handler runs at a reliable cadence. The model we use (decoupling the two threads) means that the UI thread can be a little behind, since it is calculating animations for a future frame time.

特别感谢Dwayne Need向我解释一下。

Special thanks to Dwayne Need for explaining this to me.

这篇关于为什么WPF中的帧频不规则且不受监控刷新的限制?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆