Wednesday, September 03, 2008 8:15 PM
I have an animation that uses CompositionTarget.Rendering to draw frame by frame and also calculates a frame rate. The animation is pretty intensive and runs at about 15 FPS. The calculated frame rate normally matches that given by Perforator.
I've added some text to display the current mouse position onscreen and as soon as I move the mouse while the animation is running the caluclated frame rate increases to ridiculous values > 60 FPS.
When CompositionTarget.Rendering is called I determine whether to change the values of the objects I am drawing based on the time elaspsed since the last render. When these are changed a frame draw is recorded. It seems that what is happening is that the values of the objects change but WPF drops the frame before it reaches the screen. By not having to actually draw the frame the render loop runs much faster and that is why my calculated frame rate increases. How do I determine whether a frame was dropped or has been defineatly drawn to the screen so that I can calculate and display an accurate frame rate for the animation?
Monday, September 08, 2008 3:40 AM-> How do I determine whether a frame was dropped or has been defineatly drawn to the screen so that I can calculate and display an accurate frame rate for the animation?
I don't think it's possible to calculate the frame rate only for the animation you specified, one thing you might need to know is that Rendering event will be fired whenever there is any change to the visual tree which might affects rendering, and those changed rendering data needs to be marshaled to the composition thread. You cannot determine if a frame is definitely drawn, because those frame could contain other graphical output not generated by the animation, in your case, the text update on the mouse position.
May I know why you need to accurately report the frame rate for the animation? since this "accurate" FPS is not so "interesting" enough to know about, since what's really interesting is the animation parameters/effects you need to specify/implement.
Tuesday, September 16, 2008 12:59 PMThanks for the reply. Sorry about the delay in replying to you, but this forum seems to be very unreliable at present and I've been unable to log in and post a reply the last few times I tried.
We have an application that does quite a large animation frame by frame and getting the performance up to a reasonable level has been very difficult. Some customers experience performance problems, sometimes due to poor graphics cards, graphics card drivers that do not seem to work well for WPF and so on. For support purposes it is important for us to be able to get the customer to accurately tell us the frame rate that they are seeing.
Obviously when you move the mouse around and the frame rate jumps to >60fps the actual performance of the animation on the Canvas does not improve. So is there any way to just determine how often the canvas is being rendered and not the other elements.
When you run perforator it seems to give the correct frame rate for the animation and is not affected by the mouse movements. This is the number we want to display to the user. Obviously is is easier to tell the user not to move the mouse than get them to install and run perforator, but it looks unprofessional to have this frame rate number increase like this and some users actually end up believing that moving the mouse gives you a smoother animation!
Wednesday, September 17, 2008 4:45 AM
In your original post, you indicated that in your CompositionTarget.Rendering event handler you determine whether or not to change the values based on the time elapsed since the last render. This sounds like you are targetting some specific frame rate, and only changing property values at that frequency. In general, this is a good thing.
On the other hand, WPF will respond immediately to any changes to the visual tree. WPF will immediately issue a "render" pass on the UI thread. This "render" pass does not actually render to the screen. It just gathers the changes from the UI thread and adds them to a batch of pending changes. This batch is sent over to the dedicated rendering thread, which rasterizes and presents to the screen. The CompositionTarget.Rendering event is raised each time a render pass is executed on the UI thread. This can happen very frequently if things are constantly changing.
Anyways, the CompositionTarget.Rendering event actually passes a RenderingEventArgs parameter (despite what the signature says). These event args have a RenderingTime property, which indicates the estimated present time. You can get multiple CompositionTarget.Rendering events where this property contains the same value. That indicates that the system will present the changes from all of those events at the same time. You should be able to count how many CompositionTarget.Rendering events have a unique RenderingTime property to calculate the true FPS.
Please do not send e-mail directly to this alias. This alias is for newsgroup purposes only.
- Marked As Answer by Marco Zhou Tuesday, September 23, 2008 4:14 AM