Sign in to follow this  
MartinLoga

Optimizing XNA in WPF

Recommended Posts

Hi there,

i just implemented Nick Gravelyn's Tutorial about integrating XNA in WPF ([url="http://blogs.msdn.com/b/nicgrave/archive/2010/07/25/rendering-with-xna-framework-4-0-inside-of-a-wpf-application.aspx"]This One[/url]).
Which is not using an extra window rendered over the wpf dialog but renders off screen and copies the result in to a Image Control.
In principal it's working fine but it is very slow due to copying the frame buffer many times per frame.

Bottom line it's all about optimizing the following code lines.

[code]
public void Commit()
{
// get the data from the render target
renderTarget.GetData(buffer);

// because the only 32 bit pixel format for WPF is
// BGRA but XNA is all RGBA, we have to swap the R
// and B bytes for each pixel
unsafe
{
byte r;
int length = buffer.Length;
fixed (byte* p = buffer)
{
for (int i = 0; i < length; i += 4)
{
r = p[i];
p[i] = p[i + 2];
p[i + 2] = r;
}
}
} //*/

// write our pixels into the bitmap source
writeableBitmap.Lock();
Marshal.Copy(buffer, 0, writeableBitmap.BackBuffer, buffer.Length);
writeableBitmap.AddDirtyRect(new Int32Rect(0, 0, renderTarget.Width, renderTarget.Height));
writeableBitmap.Unlock();//*/
}
[/code]

I already replaced the color conversion with an unsafe version but the performance benefit was practically irrelevant.

I tried to replace the WriteableBitmap with a InteropBitmap but there was contrary to hints in the tutorial's comments no performance increase. ([url="http://silverlightviewport.codeplex.com/SourceControl/changeset/view/39341#809062"]using InteropBitmap[/url])

Last thing I was thinking of was to replace the renderTarget.GetData(buffer); call buy directly getting the pointer to the raw data. But here I stuck ...

Based on the following tutorial ([url="http://www.xnamag.de/article.php?aid=15"]xna mag[/url]) I was able to get the IDirect3DTexture9 via the following lines ...

[code]
public unsafe IntPtr GetRenderTargetPointer(RenderTarget2D renderTarget)
{
FieldInfo comPtr = renderTarget.GetType().GetField(
"pComPtr",
BindingFlags.NonPublic | BindingFlags.Instance
);

return new IntPtr(Pointer.Unbox(comPtr.GetValue(renderTarget)));
}
[/code]

But how can I get now further? I'm not familiar with these interop and using external dll's stuff.
Next thing should be to get an IDirect3DSurface9 right?

Thanks for any help!

Share this post


Link to post
Share on other sites
The amount of time and effort you will spend trying to optimize this approach would be better spent using a different approach altogether. Nick chose that approach because it allowed him to stay inside the managed world using well known WPF primitives (and he was willing to make the performance sacrifice). Once you are willing to step outside of this box by using unsafe code or reflection, then the other approaches he outlined at the beginning of the article become much more attractive. However, understand that none of the approaches that avoid airspace restrictions will give you "great" performance, as there is a lot of buffer copying behind the scenes that needs to happen in order for it to work. If you are OK with decent to mediocre performance (which is all that is necessary for game tools) then I suggest the XNA/D3DImage interop.

Share this post


Link to post
Share on other sites
I was afraid someone could answer that.
Let's say the performance of my application is currently at the lower acceptable limit and not all requirements are yet defined. So I'm currently trying to get some extra elbowroom.
I moved the color conversion in to my shaders so I got some extra frames. Hope this will be enough for some time.

Thanks

Share this post


Link to post
Share on other sites

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