Line drawing performance in WPF

Nov 12, 2009 at 4:08 PM

My requirement is quite simple: I'd like to create an oscilloscope-type graph which shows time series data from a digital source in real time, feeding new data in on the right hand side and showing a few seconds' worth of data scrolling towards the left.

I downloaded the WPF Dynamic Data Display library, and checked out the "Animation" sample, which seems to be roughly what I want to create. However, the signal I get often varies quite rapidly, so the line segments connecting the signal will sometimes be long. Therefore, I changed the code in the Animation sample so that every second sample is the negative of the SIN, in the function that generates the signal, AnimatedPlot_Timer():

for (int i = 0; i < animatedX.Length; i++)
{
       if((i % 2) == 0)
             animatedY[i] = Math.Sin(animatedX[i] + phase);
      else
             animatedY[i] = -Math.Sin(animatedX[i] + phase);

}

This creates a realistic simulation of the signal I will actually try and display.

The problem now is that update is painfully slow. As soon as I blow the window up to a decent size, say 1000 x 1000 pixels on my screen, the update rate drops to perhaps only 6-7fps when there are 1000 points in the graph. Making the window much smaller improves the update rate dramatically. If I increase the number of points to 5000, which is what my real requirement is (data comes in at 1000Hz, and I want to show at least 5 seconds worth of data), the update rate drops to around 1fps when the window is large, again a much smaller window improves the situation dramatically.

Is this the actual limit for what WPF can do - 5000 lines a second? It seems incredible that rendering so little should take this much time, even if some of the lines are a few hundred pixels long...! But neither the D3 library nor my own code experiments have succeeded in making WPF do this seemingly simple task anywhere near as fast as GDI code.

So my question is: should I give up WPF for this requirement, or is there some optimization trick I'm missing? Any comments would be very gratefully received.

Many thanks in anticipation,

Lasse

PS HP laptop with NVidia QuadFX2700M card, WinXPsp3, VS2008 and .NET3.5.

Editor
Nov 13, 2009 at 5:16 PM

Hi Lasse,

unfortunately, now I can't name a solution that will enable WPF to render such long lines as you need quickly enough.

Maybe in the future we'll create some solution with DirectX hosted in D3DImage inside of WPF scene, but I can't name any precise dates.

Best regards,

Mikhail.

Editor
Nov 14, 2009 at 6:21 PM

Hi Lasse,

I've created a first draft of line chart using DirectX to render itself. This lineChart can be integrated into WPF's scene seamlessly, without air control conflicts and so on, by using D3DImage, provided by ЦЗАю

This chart has very nice performance - at least animated series with your modification were working in fullscreen mode (1920*1080) without any lags on my GeForce 9600 M.

So you probably should not be very sad and should not begin to search for other (for example, GDI) solution, as we are capable to provide such high performance solution by WPF+DirectX.

Best regards,

Mikhail.

Nov 16, 2009 at 10:31 AM

Hi Mikhail,

That sounds great. I actually had a similar idea myself, but using OpenGL instead of DirectX (I think I read somewhere on the Web that OpenGL is better for 2D than DirectX - which is optimised for 3D high-end games performance. Perhaps you have a comment on this?).

Anyway, using the very recently released BETA of OpenTK (www.opentk.com), I created a Windows Control derived from the Toolkit class GLControl. I embedded the Control in the WPF XASM using <WindowsFormsHost>, and now rendering 20,000 lines at 50fps without problems, even when the window is full-screen.

This really has been an eye-opener though. When I first started using WPF it seemed ideal, with everything integrated in a very nice framework based on XML. However, if the 2D (and therefore presumably also 3D) performance is so poor that rendering anything more than a few hundred simple dynamic gfx primitives per second is not possible, even when the WPF stuff is allegedly based directly on DirectX, then I must say I'm disappointed. Is it the anti-aliasing that takes such a long time? Since the performance is so dependent on the length of the rendered lines this would seem logical. Perhaps it can be turned off somehow? But since I'm seeing a performance enhancement in the order of between 100 and 1000 (!!) with OpenGL, I cannot really understand what WPF is doing. Perhaps it's taking small naps or something.

It does seem that Microsoft have taken some massive step forwards with WPF, but also some unfortunate steps back....

Regards,

Lasse

 

Jan 29, 2010 at 5:24 PM

Mikhail,

Has there been any progess on this? I have exactly the same problem, but I am bound to using WPF for my project. A solution to this would be very nice.

Thanks,

Jason

Editor
Feb 8, 2010 at 9:03 AM

Hi Jason,

currently we doesn't have some better line drawing solution than that we have now. And our experiments with DirectX and SlimDX drawing of lines are for now just experiments.

I'll inform you if some movement in this area happens.

Best regards,

Mikhail.

Feb 8, 2010 at 4:02 PM

Mikhail,

If you could get me the source code for your DirectX implmentation, I could contribute to the project by developing it further. Otherwise, I may have to create my own branch and develop it on my own. Let me know if I can help.

Thanks,

Jason

Feb 9, 2010 at 10:37 PM

Actually, I found the DirectX2D library in the latest nightly build release, so I should be able to run with it from there. I will let you know if I find any bugs.

Feb 15, 2010 at 4:33 PM

Have you made any progress Foxman?

 

A friend and I are starting a project where we need to plot several thousand markers at once, and we are thinking about trying to modify D3 to draw using D3DImage like Mikhail mentioned. We are interested in how much the performance increase will be, since plotting thousands of anything in wpf seems to be very slow.

Feb 16, 2010 at 4:58 PM

I have looked at it some, but my priorities have been elsewhere this past week. I will be working on it next week and I will post up anything I come up with.

Feb 25, 2010 at 11:26 AM
Edited Feb 25, 2010 at 11:43 AM

It is possible to switch off anti aliasing in a WPF control by setting the RenderOptions.EdgeMode property, this does bring quite substancial performance boost when using thousands of points:

<Window x:Class="Test.SimulationResultViewWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d3="http://research.microsoft.com/DynamicDataDisplay/1.0" 
    Title="Simulation Result Viewer" Height="768" Width="1024">
   <Grid>
      <d3:ChartPlotter Name="plotter" SnapsToDevicePixels="True" />
   </Grid> 
</Window>
public SimulationResultViewWindow()
        {
            InitializeComponent();

            // ... Other Code

            // Remove Anti-Aliasing from plotter
            RenderOptions.SetEdgeMode(plotter, EdgeMode.Aliased);
	}
Feb 25, 2010 at 4:49 PM

That is true, but in my case, I am drawing waveforms, so Anti-aliasing needs to be on to smooth the lines. I am still planning on the DirectX approach, but I have not had a chance to work on it yet.

Mar 1, 2010 at 6:29 PM

Just checked out your Nightly code with the DirectX shim, looks very promising. Are you still making headway on it this week?

Mar 2, 2010 at 7:03 PM

Hi all, 

I am slightly confused about the performance benefits achieved by switching from WPF to DirectX. According to Microsoft's documentation, WPF leverages DirectX,to enable hardware acceleration. I totally accept that raw DirectX code might be faster than WPF, but it seems strange to hear that DirectX is orders of magnitude faster for 2D graphics. Can any of you good people explain this enormous difference?

I've built a data display program that scrolls output from a scientific instrument (an SRS boxcar integrator). On a machine that WPF recognizes as having Tier 1 graphics acceleration, I can plot around 3k points on screen, refreshing at about 1Hz. On a system without any hardware acceleration (Tier 0) I am luck if I get 1/3 that performance. So it certainly seems like DynamicDataDisplay is leveraging at least some hardware acceleration as-is. NOTE: for info about WPF graphics tiers, click the link above.

And Liam, thanks very much for the anti-aliasing trick, it looks very promising.

 

Thanks,

James Remeika

University of Miami

Mar 2, 2010 at 8:43 PM

James,

It's down to the 'retained mode' graphics which WPF uses, essentially, each Point, Series, Graph etc. is stored as object(s) (i.e. retained) by WPF, this way you can manipulate the objects - change properties (e.g. colour, line thickness) , assign events (e.g. onclick) and so on after they have been drawn. WPF then automatically redraws the scene when a property changes or event occurs, but this comes with an overhead cost.

If you used 'immediate mode' graphics such as what DirectX offers (or WPF WriteableBitmap), the graph objects are drawn directly to an image as pixels, which are then presented to your screen. You could then translate, scale, rotate the entire image by using Matrix transforms but you could not change the properties of the previously drawn elements.

Hope this helps!

Liam

Mar 4, 2010 at 5:31 PM

Liam,

Thanks for the thoughtful reply. That makes perfect sense. 

James

Mar 11, 2010 at 1:26 PM

Is there a sample in the solution for direct x rendering? what is the current project status? is there still any active development? The latest official release is nearly one year old.

 

Regards

Aug 31, 2010 at 7:02 PM

bump

Just wanted to bring this up again as I'd love to see the sample as well.