Визуализация SharpDX в WPF

Я хочу рисовать линии как можно быстрее. По этой причине я реализовал метод, используя InteropBitmap. Это работает довольно хорошо. Следующим шагом было сравнение с ShardDX. В основном то, что я хочу сделать, это: Запуск следующего кода в BackgroundWorker. Это сообщает WPF об обновлении WIC. Я узнал, что этот код (создание всего необходимого для ShapeDX и draw line) занимает около 10 мс дольше, чем при использовании InteropBitmap.

мой вопрос сейчас просто, как ускорить? Могу ли я как-то изменить код, который мне нужно только вызвать BeginDraw, создать строки и EndDraw, не всегда делая все это кодирование/декодирование изображений? Или есть лучший подход?

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();

С:

System.Windows.Media.Imaging.BitmapFrame _WIC;
    public System.Windows.Media.Imaging.BitmapSource WIC
    {
        get
        {
            return (System.Windows.Media.Imaging.BitmapSource)_WIC.GetAsFrozen();
        }
    }

и:

<StackPanel>
   <Image Name="huhu1" Source="{Binding WIC}" />  
</StackPanel>

3 ответов


SharpDX Toolkit поддерживает WPF через общую текстуру Direct3D11-to-Direct3D9. Он реализован в SharpDXElement класса.

возможно, вы не сможете повторно использовать это, поскольку Direct2D (который вы используете для рисования) может взаимодействовать с Direct3D11.1 или Direct3D10 и SharpDX используют Direct3D11 для поддержки WPF, поэтому вам нужно будет немного настроить решение.

в основном вам нужно сделать следующий:

  • инициализировать Direct3D (10 или 11.1).
  • Инициализации В Direct2D.
  • создайте цель рендеринга D3D с поддержкой Direct2D и Shared флаг (здесь как это делается в SharpDX).
  • инициализации Direct3D9.
  • создать общую текстуры.
  • свяжите текстуру с D3DImage.

Не забудьте звоните D3DImage.AddDirtyRect при обновлении содержимого целевого объекта рендеринга.

из предоставленного вами кода неясно, выполняете ли вы все инициализации только один раз или нет, поэтому попробуйте вызвать любой код инициализации только один раз и повторно использовать цель рендеринга - просто очистите его в начале каждого кадра. Это обязательно, чтобы получить достойное представление.

Обновление: SharpDX.Инструментарий устарел и больше не поддерживается. Он переехал в отдельный репозиторий.


Если вы хотите поделиться поверхностью directx с WPF, лучшим вариантом является использование WPF D3DImage. Он обещает работать без копирования, если вы используете правильный формат цвета.

Я использовал его только с Directx9, но возможно, что его совместимость с Direct2D тоже, но если это не D3d9, тоже может рисовать линии.

есть большая статьи codeproject с примерами. Из управляемого кода, используя slimdx и sharpdx единственным необычным предостережение этот D3DImage сохраняет счетчик ссылок на вашу поверхность DirectX, поэтому вам нужно неявно обнулить backbuffer, когда вы хотите сбросить устройство d3d.


можно использовать Smartrak / WpfSharpDxControl: обеспечивает управление WPF для размещения содержимого SharpDx.

Он использует sharpDx в WPF, и wpf может добавить Win32HwndControl в HwndHost.