Sign in to follow this  

Fast 2D charting in .NET

This topic is 665 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi,

 

I am writing my own charting assembly for .NET

The goal is to be able to draw 50k points with automatic chart scaling on different windows (within the same process) at 60 FPS on a modern hardware

 

Thinking that 50k is a lot and having no experience at all in graphic application development I decided to go for the most suitable, as the developers say themselves, drawing subsystem - Direct 2D.

 

After implementing that I got about 10 FPS.

Several optimization steps (resource preallocation, resource preinitialization, caching, profiling and so on) it got up to 30-40 FPS which is still unacceptable.

Currently I am unable to perform further optimization because 80% of the time is spent during actual interaction with SharpDX Direct2D wrapper (95% of that time is spent between BeginDraw and EndDraw)

 

I tried to get familiar with Direct3D 11 and is now stuck with some points that require a lot of time to be invested in to understand the undergoing processes in order to come out with decent result (starting from - there is no concept of 'DrawLine', ending in - what do I do to get a constant chart margin to draw arguments on, should I calculate the transformation myself? on CPU or GPU side? how to pass a transformation matrix to a shader? how to build it?..)

 

The questions are:

 

1. Is it even possible to achieve the posed goal?

2. Where should I look next to get closer to 60 FPS?

 

PS. Currently typical chart looks like this: 

 

a7019bd613a74841833a524fdae90b1a.png

Share this post


Link to post
Share on other sites
Modern hardware works best with few large batches, rather than many small ones.

You will want to minimize the number of draw calls (and therefore effective state changes) as much as possible.

Share this post


Link to post
Share on other sites
Also, the graphics hardware generally implements rasterization of triangles, single-pixel wide lines and single-pixel points. For anything else, you need to use your own logic to expand these, or use an engine that does this for you.

Share this post


Link to post
Share on other sites

1. Is it even possible to achieve the posed goal?

Of course.

2. Where should I look next to get closer to 60 FPS?

I don't see why DirectX should not be your option.

Invest some time and learn the technology. Drawing lines is a simple task for modern hardware. You just need to know how to handle the data and draw it.

 

If you are interested in a most suitable UI solution, (WPF), you can try this: 

http://dynamicdatadisplay.codeplex.com/SourceControl/latest

Share this post


Link to post
Share on other sites

Yes, make it faster, but I wouldn't do it by going for a hardware rendering route here.

 

The fastest tasks are the ones you never run.  You may have 50,000 data points, but the graph consists of a 1000-ish pixel window with three charts drawn. It looks like this is a time lapse view, so you really are just sliding over a previously-computed display and adding new rows to the end.

 

Do the hard processing just once, or as infrequently as possible.

 

When you first need to draw all the stuff do it once, store it in an image, perhaps just storing it in a new bitmap. Maybe implement it as 5 or 10 or some number of strips to make updates easier.  With those saved off you will never need to process the points again, the graphics for them are already computed and ready to be blitted to screen as often as needed.

 

As time slides the panels, move those existing segments to the side and re-blit them.  For new data points coming in, build and accumulate a new bitmap for that segment of the panel, and draw the parts that have been computed already. When the segment meets the new full size, slide it over and start a new segment.

Share this post


Link to post
Share on other sites

Oh, as for when you need to change the scale, you can track the scale of each panel segment rather than the full data set.  When you need to shift your scale, rebuild all the panels. You could run it in another worker thread, building them from most recent to oldest, and when they're complete swap them out.

Share this post


Link to post
Share on other sites

Thanks to everyone.

 

Implemented using Direct 3D 11.

I am using triangle strips and dynamic buffers which gives me 100k points at 60 fps.

I can invest more time optimizing but I am already twice ahead my goal so I decided to stop here.

Share this post


Link to post
Share on other sites

This topic is 665 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this