The WPF API’s work hard to abstract away the grungy details of rendering pixels to the computer screen. It’s still work to build nice looking user interfaces but it’s getting easier to think about the design instead of worrying about video buffers and framerates. The complexity is still there, but someone at Microsoft is dealing with it so that we don’t have to.
Talking about the details
I was reminded of this today when I read this forum thread today. David Teitlebaum (Microsoft) explains why a 3D animation is running so slowly on a particular video card.
WPF3D will use 4x multisampling on vista by default, so your 1280 x 1024 viewport3d is being rendered into 2560x 2048 mltisample color and depth buffers. Color will be be 4 bytes per pixel (RGBA), depth will be 4 (3 byte depth, 1 byte stencil). Each multisample texture write requires a texel (4 bytes) of readback (since alpha is enabled) and a depth readback for ztest (4 bytes) Moreover, image brushes use mip mapping, so each texel read is actually 8 reads (4 for bilinear from each of the two relevant mip map levels). Actually I think we’re using anisotropic filtering but I’ll ignore that. We use multisampling instead of supersampling, so the number of texel reads isn’t again multiplied by 4.
The contents from the multisample buffer have to be downsampled/copied into the window’s shared surface each frame, and that surface’s content has to be copied to the back buffer each frame.
The dirty regions of the viewport3d’s multisample buffers (color + depth) have to be cleared each frame.
writing (2560x 2048) * (4+ 4) [clear dirty multisample buffers]
writing (2560x 2048) * (4 + 4) [multisample color + depth write]
reading (2560x 2048) * (4 + 4) [alpha and z read]
reading (1280 x 1024) * 8 [using 2 mip levels with 4 reads each for bilinear]
reading (2560x 2048) * 4 [read finished multisample buffer]
writing (1280 x 1024) * 4 [write it into shared surface]
reading (1280 x 1024)* 4 [copy dirty shared surface to back buffer]
writing (1280 x 1024) * 4
Ok, so I did the math and get that the video memory bandwidth is 173 megabytes (173,015,040 bytes) per frame. At 60 fps, that translates to 10 gigabytes (10380902400 bytes) per second.
According to this page, the go 7400 has 7.2 GB/s of memory bandwidth. So you are probably video memory bandwidth-limited and this is causing your crappy frame rate.
Disable multisampling, disable clip to bounds, and make your viewport3d smaller if possible.