batchprogram
batchprogram

Reputation: 11

WPF Slow Tilemap Rendering Performance

I've been working on migrating my existing tilemap editor based on XNA/WinForms to WPF. I'm rather new to WPF, but most of the concepts haven't been too difficult to grasp. I have a Viewbox embedded into a ScrollViewer, using the DrawImage method from the DrawingContext provided by the (Viewbox)derived OnRender method to draw the map. The problem is I cannot achieve anywhere near the same performance as with the XNA/WinForm version when a rather large amount of tiles are on screen(>1000 on my machine). I have implemented zooming and panning, but when I zoom out too far or pan when a large amount of tiles are on screen, there is major lag which ruins the user experience. I have taken several obvious optimization measures(freezing the source bitmap, culling tiles that cannot be seen, setting the bitmaps scaling mode to LowQuality, providing the Cache caching hint), but they don't seem to resolve the issue. The problem is obviously in the way WPF handles drawing textured quads with DrawingContext.

I have provided a sample application with all of the code necessary to reproduce the problem: SampleGridDrawingExample

Hold the middle mouse button and move the mouse to pan. It becomes more and more noticeable as the size of the window increases(obviously because more tiles are being rendered).

Is there a faster method than DrawingContext within WPF to draw large amounts of textured quads with reasonable performance?. Using XNA/WinForms I can draw ~50000 tiles in multiple layers with reasonable lag, whereas in WPF using my current approach going over 1000 causes noticeable lag(>10000 brings the application to a crawl).

Upvotes: 1

Views: 1078

Answers (3)

Asik
Asik

Reputation: 22133

WPF does use hardware acceleration, but very inefficiently - it makes way too many draw calls for everything. Its 3D rendering capabilities are meant for enhancing user interfaces, not heavy-duty rendering (such as drawing tens of thousands of individual elements). It is possible that your code can be optimized, but certainly nowhere near the level of performance XNA gives you.

A better option for you would be to build the editor in WPF, but keep the renderer in XNA and host it inside the editor.

Upvotes: 1

batchprogram
batchprogram

Reputation: 11

It seems that with WPF alone, it's currently impossible to get anywhere near the performance of XNA. However after taking a look at Nick Gravelyns post on XNA integration, I settled on using the method listed there, as the performance is acceptable for the application I'm developing. After a bit of modification to the sample and subsequent stress testing, I managed to make it stable enough for production code. I highly suggest anyone who is interested in XNA->WPF integration to take a look at that post.

Upvotes: 0

Sebastian Edelmeier
Sebastian Edelmeier

Reputation: 4157

I have downloaded your sample and it works alright for me, no major performance lags. If I monitor my performance, though, you seem to have some kind of bottleneck in whatever calculation you perform whenever the mouse is moved. See the attached screenshot, which illustrates CPU usage when moving the mouse a lot (left half of the image) and moving it infrequently (right half).

CPU usage

I assume rendering is not what slows things down, but other code in your event handlers. To ascertain, I set RenderOptions.ProcessRenderMode = System.Windows.Interop.RenderMode.SoftwareOnly;, which behaves in exactly the same way on my machine (Good CPU, moderate GPU). I checked this for Memleak issues as well, but regarding that, it looks OK - On my 64Bit windows, Memory usage never exceeds 64Megs and garbage collection effectively frees the resources now and then.

You mention your previous solution. What portion of your that solution was based on XNA? XNA relies on Hardware acceleration (so does WPF as per default), WinForms on the other hand is purely CPU accelerated. Who runs your old magic, your CPU or your GPU?

Upvotes: 0

Related Questions