Tuesday, March 21. 2006WPF- Pick Your API Abstraction
Recently we have been getting several questions on hardware acceleration. Some folks are running the Perforator tool and noticing that although it indicates that their application is running in hardware, the application is still taxing the CPU. This may seem confusing, so I will try to give some background in this posting, as well as cover the factored access/extensibility points within Windows Presentation Foundation and the technologies it builds on.
Compute versus Render Bound Over time, we have found that most applications are compute bound (I am talking about Win32 applications here). They spend most of their time performing calculations on the CPU, and this becomes their performance bottleneck. With text applications, this can because of paragraph layout calculations. For games it may be because of the physics engine. Very few applications turn out to be render bound (games included). However, if you try to do 3D graphics or render with higher quality (anti-aliasing or sub-pixel ClearType) in software, as well as just do a lot of rendering (scientific visualization and CAD programs), the application is likely to become render bound. With WPF, we offload a lot of the rendering work to the GPU, and thus are able to provide high quality graphics without swamping the CPU. The bottom line for us is: if the CPU is busy doing graphics, it is not doing some other important task. And, we dont want that to happen. We want the CPU always to be busy doing useful work, and leaving the graphics to the GPU. Also, as we develop WPF, we try to make it as much render bound as often as possible. This way, as your end users get better graphics hardware, and the hardware evolves, the performance and/or quality of your application improves. Hardware versus Software Rendering There are some situations which will cause WPF to fallback to software rendering (this is more common in pre-Dx9 video cards or when performing some operations). When this happens, the CPU gets to do more work and likely the overall performance of your application goes down. In many cases, this takes place inadvertedly, thus the need for the Perforator tool, to help track down the cause of falling back to software. There is also a programmatic way of determining whether one is rendering with hardware or software, through the tiering API. Perforator is a bit handier, because it is interactive (for example, you can modify some XAML in XAMLPad and see how it affects hardware acceleration through Perforator). However, you should still use the tiering APIs to adapt the content that your application presents, so that it can work equally well on lower end machines running Windows XP, in software mode. Factored Access to WPF It is clear from the questions/discussion in newsgroups that some folks are solely after fast graphics rendering, and perhaps not that interested in the high level/framework services that WPF exposes. Yet, when they use WPF, they feel that they are not getting all the graphics performance they want. We think of WPF as having two major parts, the MIL (Media Integration Layer) and the Framework. The majority of developers will program at the Framework level, and so this is where we focused the development of the SDK first. Some developers do not need the Framework services (Layout, Input, Focus, Eventing as well as styling, databinding, and XAML). They just want the graphics. For those folks, we provide the Visual layer. A Diagram of API and Extensibility Points Hopefully the diagram below will bring to light the different API entry points, as well as the extensibility points, both in WPF and on the technologies we build on. At the top if the Framework. This is the most common programming abstraction and it is what provides controls (Button, Menu, etc), as well as Layout (Canvas, Grid, etc), and the ability to extend those. It also includes services such as databinding and styling. We use our public APIs to build our own components. This validates the architecture and implementation we built. This means that anyone can develop layouts and controls that are able to match the performance and functionality of the built-in elements (unlike for example in the HTML world, where there are not enough programming abstraction exposed, for example, to build the Table element and perform other layout operations). At roughly the same level of abstraction as the Framework is XAML-Presentation. We expect that many tools will generate/consume XAML-P, even if not all of those applications are not built using WPF (we have examples of third party and Microsoft applications that fall in this category today already). Below that, we have the MIL. It presents an API called Visual, which allows developers to do rendering, without a lot of the services available at the Framework level (lower policy, therefore with higher performance in some cases, as there is no layout involved or property system). This marks the transition from managed to native code. The last API layer below Visual is WPF Imaging Components (WIC), which enables native code applications also to leverage the imaging functionality in WPF (this functionality is exposed at the Framework level as well). Now we are below the API layer, and into base extensibility points for providing support for new formats, for example. We will begin with WIC Compressors/Decompressors (CODEC), which enable anyone to extend the supported imaging formats on the machine (on Windows Vista, the end user benefits directly from new CODECs in their desktop experience). Next are Effects, which enables developers to add their custom image based effects (Geometry based effects will have to wait until a future version of WPF). There are also extensibility points in the technologies that WPF uses, which get exposed or used by WPF applications indirectly. The more interesting type are DirectShow filters. This enables developers using WPFs media element to effortlessly playback different media types (similar to WICs CODEC, which provide seamless support for new imaging formats). Hardware folks can provide support for their custom hardware through Direct3D drivers (Windows Display Driver Model in the Windows Vista case) and Print drivers (XP print driver model or Next Generation Print Path drivers these last type uses XPS as its spool format). update 05/23/07 - Here is an interesting posting of using WIC for getting DShow content into your WPF application Jeremiah Morrill's blog entry. Comments
Display comments as
(Linear | Threaded)
Great thing. Thank you, Pablo, it is nice review to get in touch with WPF architecture.
You state that "The bottom line for us is: if the CPU is busy doing graphics, it is not doing some other important task."
So far, in my experiences of WPF, the CPU has been very very busy. It would have been nice for the whole of WPF to live on the GPU. Can we imagine a retained-mode API that lives entirely on the GPU, implemented with vertex and fragment shaders? We will get closer to the picture you paint over time.
The new driver model in Windows Vista enables us to take a big step forward. The Advanced Driver model post Windows Vista will enable even greater use of the GPU (the interrup level will be more granular). Eventually we will get to Dx10 parts being the base requirement for the OS (not in Vista, which is Dx9 based), and we will offload even more work to the GPU. But even then, we will always have the CPU do some work (property level operations at least, likely layout as well), especially where there is high frequency back and forth with the application. In terms of WPF v1.0, how busy the CPU is can be related to: 1) bug in our code 2) cost of the operation on our side 3) cost of the operation on the application side 4) side effect of how our code is being used If you can send us an example of your usage, we can track it down. Thanks for the comment! -Pablo Hi Pablo,
My code has already been profiled at Microsoft. It turns out that nearly 40% of my CPU usage is coming from code that should be implemented on the GPU (lighting calculations), another 15-20% is coming from bad implementations (e.g. performing a PInvoke for each and every vertex, normal, etc in a 3D mesh), and another 10-15% is coming from various other issues that can be worked around or ameliorated. Hi Daniel,
I've been tracking the work that we are doing based on your feedback. Thank you for sending that in. I would like the lighting calculation to be performed on the GPU, let's see what gets done for this first version. -Pablo Finally, one of the first articles that wants to talk about extending WPF with 3rd party functionality. I have been searching for this kind of information for quite some days now. I see that you're talking about DirectShow also, and this is what I want to know.
I have a library that so far can preview webcam video in Windows Forms and Direct3D. It uses VMR9. Knowing that WPF is based on Direct3D, I thought implementing it in Avalon also wouldn't be too hard. But it is, because I cannot find the proper documentation and samples. So what I want to know is how to implement this. I saw samples of MediaElement playing video inside shapes or on a 3D cube (Hands-On-Labs). I would like to achieve similar functionality with my library. How can I do this? What should I subclass? Are there any examples so far? Thank you, Cosmin. The Visual is still fundamentally a retained-mode API, storing data that is then rendered using the rendering thread. Is this statement correct?
If so, this is the biggest problem we have with using WPF in techincal applications. Fundamental optimization techiques are no longer available -- reusing the same rendering data for multiple objects, optimizing buffering, incremental rendering optimization (only changes re-rendered), controlling framerates... Will we ever have acces to a true immediate mode API? The Visual layer is indeed a retained-mode API. Once you try to integrate animations and audio/video with other graphics types, you find that this model is best suited for that.
In terms of the optimizations, we do incremental rendering and buffering for you. You can re-use data (as in brushes or resources) from the API. Framerate is dependent on the machine/scene, we try to drive the scene as fast as it can on the machine (or you can drive the clock yourself, if you want to capture frames), but you can provide hints if some animation is less important (so we ran it at a lower rate). Hope this helps, -Pablo When I said "buffering" I was speaking of buffering the rendering data.
For example, if I wish to draw a polyline using the lowest level interface available (DrawingContext): A) How many times are the polyline points copied from one memory location to another before rendered, starting from the original API call? B) Are the points transferred across a bus, such as the video bus? The answers to those questions determine in part how well the system scales when the number of points increases to many megabytes. When I speak of reusing rendering data, it is not just brushes, I mean any type of data, with minimal data transfer. What you call "animations" in WPF speak seems to be mainly Flash-style advertising type of animations? In many technical applications animation is driven by real-time data and is fundamentally imperative -- no interpolation. This is why it is important to have low-level control over the screen updates. Incremental rendering optimization: suppose I draw 100K polyines with the lowest-level WPF API, DrawingContext. Now I wish to change 10 of those polylines in response to a change real-time data. Must I re-stream all 100K? With an immediate mode API and a bitmap or video buffer based system it is possible to optimize this scenario. With the DrawingContext what does one do? If the solution is to abandon WPF, and go back to GDI, GDI+, or attempt to fit a 2D immediate mode system over DirectX, this is disappointing. We have been waiting for an update to GDI+ for many years now. Maybe the The Visual layer is not quite a fit for CAD level programs but should improve less-demanding desktop apps a lot. Are there any documentation for the The Visual layer APIs? I am eager to try it.
The perceived problem you have comes from not understanding how data binding works in WPF. By using databinding, your animations can be driven by data. For a number of examples related to data driven animation in WPF, you should look at http://www.thewpfblog.com
I am also interested to know the answers to the questions Frank asked in the above post. If you don't know the answers or don't have time to answer or whatever, pointers to information that helps to answer them or to better places to ask would be most appreciated.
Could you please update all links in your article?
They are no longer vaild. I've heard that MIL API is not public.
Also, it is unmanaged API, not managed as written in the blog. As you see in the diagram, the lower level layers of the MIL are written in native code (unmanaged), which is where the MIL interfaces with Direct3D, for example.
Not sure why one would think that the MIL is not public. The lowest level API exposed for the MIL are Visual, and that is managed. Obviously, the MIL is also exposed/used by the framework level APIs as well. Below the MIL, you have access to the Windows Imaging Component and Direct3D, both through native APIs. Well, there are no header or lib files publicly available for milcore.dll, right?
Being able to use MIL from unmanaged applications is what the fuzz is all about. Please don't say now you didn't know why anyone might want to do that Thanks for the link back to my blog!
In response the "Factored Access to WPF" section. I believe a lot of developers want their cake (WPF) and eat it too (Fast Graphics Rendering). With the framework level functionality, we can do all sorts of great effects with vectors, alpha blending, animation, etc. We can even use the BitmapEffect API / BitmapSource.Create() to do modifications to raster images. The issue is performance of these methods as the framework API seems to reallocate an image's buffer and cause insane amount of page faults and overall CPU usage. This makes WPF unusable in some situations. We can always use Win32 Interop, but we lose out on all the WPF goodness. Say I had a video chat application I wanted to port to WPF. I have a custom DirectShow graph that takes a webcam stream and sends to a renderer and out to the network. It is impossible to render the video for WPF compositing (w/o killing the CPU). What if I had a Photoshop-esque application and I wanted direct access to the pixels for modification. Again this is impossible to do efficiently in WPF. I am very optimistic that Microsoft will have a solution to these issues in future updates to WPF. I admit I have been very a very annoying voice, trying to be a squeeky-wheel in hopes to expedite this ability. I believe the missing high-performance graphics access really inhibits the type of applications that can be made and promotes usage of win32/winforms interop, something we should all want to get away from. -Jer The "missing piece" of WPF is not completely captured by the phrase "Fast Graphics Rendering". The other part is scalable graphics rendering. WPF is (currently) a retained-mode-only API. There are classes of applications for which retained mode simply does not scale well enough to be practical. My example is scientific visualization, where you have vast amounts of data you are trying to display on-screen. WPF is a great API if you have a small number (a few thousand) of objects that move around. For those of us with a large number (hundreds of thousands to millions) of objects that sit still, WPF is quickly overwhelmed, primarily in terms of the amount of memory it consumes rather than rendering speed. This class of applications needs, IMHO, an immediate-mode API that integrates with WPF. It's been mentioned (Tim Cahill's blog I think, a year or so back). Can we have it please ;-)?
I am working on a graphics intensive application. I need to display tens of thousands of polygons, a few filled with linear gradient fills, others with uniform color, support VERY LARGE zoom ratios. Data is static. I do not need any hittests on the shapes displayed.
I implemented the app with .Net 2.0 framework. Performance is reasonably good. GDI+ crashes frequently because of "overflows" and "underflows". I reimplemented the app with WPF but not able to get reasonable performance. I used a canvas contained in a ScrollViewer to display the data. In OnRender I used PathGeometry objects and DrawGeometry() method to render all the shapes. It is taking considerable time to render the data. If I scroll using the scroll bar it calls OnRender(). I would appreciate if the following questions are answered. 1. Is the strategy I use optimal? 2. Is there a way to tell the system "there is no change use cached retained mode data" in response to Render event? 3. Is there a way to suppress calling of OnRender() when scroll position is changed? 4. When I use Perforator I see only "software render targets". No "hardware render targets". My system has DirectX 9.0c. Why is it not using HW acceleration? -Rammohan Rammohan,
If you want good performance from WPF, you must factor all code out of OnRender. If you are drawing with geometries, I believe the steps are: Create a Drawing or DrawingGroup from your Geometry (probably a GeometryDrawing). Then, create a DrawingVisual, call RenderOpen on it, and use DrawDrawing to render the drawing into the DrawingVisual. Finally, you need a FrameworkElement that you can put on the canvas. I have a class called VisualHost that derives from FrameworkElement, takes a DrawingVisual as a constructor argument, overrides VisualChildrenCount to always return 1, and overrides GetVisualChild to return the DrawingVisual. It is that VisualHost that gets put on the canvas. Hope this helps. Eric I appreciate that clarification Eric. Is your VisualHost class nontrivial.. and may I have a looksee?
My own application right now is using OnRender to draw a pile of data-plots, each containing thousands of datapoints, and is unacceptably slow. I'm handling OnRender for every time the user does a horizontal scroll. Would then the better method be to use a ScrollViewer, load it with the entire set of data-plots and let IT do the scrolling (factoring all of my rendering code out of OnRender as you said)? Thanks, James In response to rendering a Geometry as a GeometryDrawing the using DrawDrawing. Would it not be more effective to use the DrawGeometry() call rather than DrawDrawing?
Why bother creating your Geometry as a drawing just to use the DrawDrawing call? Rob You're quite right. In my sample app that uses geometries, I am creating a DrawingGroup of a bunch of different elements (multiple geometries drawn with different brushes/pens, plus text elements) that I need to be able to transform together. The only way to do that was to turn my geometries into drawings, hence the use of GeometryDrawing. Absent that requirement, DrawGeometry() would have been the way to go. Thanks for clearing that up.
Thanks that is a good point. I am drawing with drawing visuals and rather than creating a drawing group I was creating a bunch of separate visuals. Your reply points to using less Drawing Visuals and more Drawing Groups when appropriate
Also consider creating a DrawingVisual which implements Shape and it's decedents. This is a path to developing a library of shapes which could have a compatible interface in silverlight. Specifically shapes, brushes, pens can be drawn in a similar fashion with silverlight shapes. If one had a goal to create a ui implementation which would compile to presentationCore and silverlight 2.0 they could do it by standardizing on Geometry as their UI model data. This would have to also include brushes and a pen.
If you look closely at System.Windows.Media in both PresentationCore.dll and Silverlight 2.0. you will see the overlap classes available in terms of rendering Geometries using a Path, brushes and a pen. The only place it differs is Silverlight 2 has a videoBrush and PC has a VideoDrawing. Example you create a drawingVisual Shape base class that does the same thing as SilverLight 2.0 shape. Derive other shapes and now you have two compatible drawing classes. Compatible in terms of both set of shape classes share the exact same Geometry, brush & pen to render. Also they implement the exact same dependency properties and animation classes. The code base only really have to diverge with the host container as a window or browser. The preceeding design excludes the use of a drawing group as there is no common silverlight class. Each DrawingVisual is equivilent to silverlight 2.0 shape in terms of making the code cross compilable. Does this prospect interest you? If so perhaps you should not post this comment rather email me directly. I could share the current implementation of a silverlight compatible PresentationCore.dll MVP user control implementation. Thanks so much. Rob Anyone have any benchmarks on how much hardware acceleration will speed up various operations?
Looks like we're close to the topic i need to discuss here, so need input why the heck my app is rendering in software mode.
The app displays long polylines in a couple of long canvases. they are in a scrollpane so the user can scroll up and down to view the full content. The canvases have tiled rectangles filling them which have geometry added to draw gridlilnes in the background. The problem Im having is anytime a scroll is done, the canvase contents are re-rendered, and in software mode. Makes for a sluggish scrolling operation. I cant find anything fancy Im doing that might cause the software rendering to occur... Im lready looking to switch to the virtualizing canvas (that I found code for online), but just having this render in hardware mode would seem to help things quite a bit. Im testing on xp sp3 with directx 9.0c, with an nvidia 256 mb vid card. It is a laptop, if that matters. Thanks It is useful to everyone.very good opinion.would be much easier for designers and translates them very easy to work.
Add Comment
|
Calendar
QuicksearchCategoriesLive SearchSyndicate This BlogXBox 360 Gamer Tag |
||||||||||||||||||||||||||||||||||||||||||



I was going to post something about the various levels you can use in WPF for graphics, but Pablo Fernicola...
Tracked: Mar 21, 14:39
Такая обзорная статья на тему архитектуры WPF. Что внизу, что сверху, где есть р
Tracked: Mar 21, 16:06