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; }
Two things surprised me:
Y - Time between frames in ticks (10,000 ticks = 1ms)
X - Frame count
Possible confounding factors
The project I'm using: SimpleWindow.zip
===Edit
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
RenderingEventArgs.RenderingTime.Ticks
Data from RenderingEventArgs produced data much closer the expected 16.6ms/frame, and it is consistent.
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.
Best answer: The refresh rate of your monitor won't affect your game's frame rate, but it will affect how many of those frames you see.
Refresh Rate vs.Refresh rate is a measure of how many frames a monitor can refresh every second. FPS, however, is a measure of the ability of the graphics card to draw a number of frames on the display each second. While both are a measure of different things, they are directly related and affect each other.
I raised this question with the WPF team and here is a summary of the response I was given:
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.
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.
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.
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.
Special thanks to Dwayne Need for explaining this to me.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With