I want to draw lines as fast as possible. For that reason I implemented a method using InteropBitmap. This works quite good. Next step was to compare with ShardDX. Basically what I want to do is: Running the following code in a BackgroundWorker. This does inform the WPF about an update of WIC. I found out that this code (creating all needed for ShapeDX and draw line) takes about 10ms longer than doing the same using InteropBitmap.
My question now is simply, how to speed this up? Can I change the code somehow that I only have to call BeginDraw, create lines and EndDraw, not always doing all of this Image Encoding/Decoding stuff? Or is there a better approach?
var wicFactory = new ImagingFactory();
var d2dFactory = new SharpDX.Direct2D1.Factory();
const int width = 800;
const int height = 200;
var wicBitmap = new Bitmap(wicFactory, width, height, SharpDX.WIC.PixelFormat.Format32bppBGR, BitmapCreateCacheOption.CacheOnLoad);
var renderTargetProperties = new RenderTargetProperties(RenderTargetType.Default, new PixelFormat(Format.Unknown, AlphaMode.Unknown), 0, 0, RenderTargetUsage.None, FeatureLevel.Level_DEFAULT);
var d2dRenderTarget = new WicRenderTarget(d2dFactory, wicBitmap, renderTargetProperties);
var solidColorBrush = new SharpDX.Direct2D1.SolidColorBrush(d2dRenderTarget, SharpDX.Color.White);
d2dRenderTarget.BeginDraw();
//draw whatever you want
d2dRenderTarget.EndDraw();
// Memorystream.
MemoryStream ms = new MemoryStream();
var stream = new WICStream(wicFactory, ms);
// JPEG encoder
var encoder = new SharpDX.WIC.JpegBitmapEncoder(wicFactory);
encoder.Initialize(stream);
// Frame encoder
var bitmapFrameEncode = new BitmapFrameEncode(encoder);
bitmapFrameEncode.Initialize();
bitmapFrameEncode.SetSize(width, height);
var pixelFormatGuid = SharpDX.WIC.PixelFormat.FormatDontCare;
bitmapFrameEncode.SetPixelFormat(ref pixelFormatGuid);
bitmapFrameEncode.WriteSource(wicBitmap);
bitmapFrameEncode.Commit();
encoder.Commit();
ms.Seek(0, SeekOrigin.Begin);
// JPEG decoder
var decoder = new System.Windows.Media.Imaging.JpegBitmapDecoder(ms, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
// Write to wpf image
_WIC = decoder.Frames[0];
// Tell WPF to update
RaisePropertyChanged("WIC");
bitmapFrameEncode.Dispose();
encoder.Dispose();
stream.Dispose();
With:
System.Windows.Media.Imaging.BitmapFrame _WIC;
public System.Windows.Media.Imaging.BitmapSource WIC
{
get
{
return (System.Windows.Media.Imaging.BitmapSource)_WIC.GetAsFrozen();
}
}
And:
<StackPanel>
<Image Name="huhu1" Source="{Binding WIC}" />
</StackPanel>
SharpDX Toolkit has support for WPF via a Direct3D11-to-Direct3D9 shared texture. It is implemented in the SharpDXElement class.
You may not be able to reuse this as is because Direct2D (which you are using to draw) can interop either with Direct3D11.1 or Direct3D10 and SharpDX uses Direct3D11 for WPF support, so you will need to tweak the solution a little bit.
Basically you need to do the following:
Do not forget to call D3DImage.AddDirtyRect when the contents of the render target are updated.
From the code you provided it is not clear if you are doing all initializations only once or not, so try to call any initialization code only once and reuse the render target - just clear it at the beginning of every frame. This is mandatory to get a decent performance.
Update: SharpDX.Toolkit has been deprecated and it is not maintained anymore. It is moved to a separate repository.