2012-04-23 3 views
8

Я являюсь частью команды, которая создала инструмент для просмотра и взаимодействия с очень большими и сильно взаимосвязанными графиками в C#/WPF. Просмотр и взаимодействие с графиком осуществляется с помощью настраиваемого элемента управления, который принимает набор DrawingVisuals и отображает их на холсте. Узлы на графике могут иметь пользовательскую форму, созданную с помощью нашего редактора. Текущий контроль работает очень хорошо и довольно сочетается с нашей программой, но есть законные заботы о производительности при рассмотрении гораздо больших графиков (20 000+ узлов и много соединений).2D Drawing Performance (GDI + vs SlimDX)

После этого несколько исследований, кажется, эти два подхода:

  • GDI + маршрут, где графика обращается к WriteableBitmap или InteropBitmap.
  • SlimDX или DirectX вариант (размещается в D3DImage)


Учитывая эти два чрезвычайно разные подходы, какой маршрут лучше всего было бы взять с учетом:

  • Взаимодействуя с графиком должен быть быстрым, даже при просмотре всего графика.
  • Обновление визуальных изображений должно быть быстрым (изменение цвета или размера)
  • Испытание на удар должно быть быстрым (точка и прямоугольник).
  • Разработка должна быть завершена своевременно.

Какой метод вы бы использовали и почему?

EDIT:
Похоже, что similar question был задан, но не ответил.

+0

GDI + медленный. GDI быстро, но некрасиво. D2D лучше, но медленнее. SlimDX - это огромная зависимость и большая абстрактная кривая обучения. 3-й вариант, используя DX9 или (DX11 через DXGI), когда он дрожит с интерфейсом WPF D3DImage. Предоставлена ​​кривая обучения, но более удобна для создания 3DX-устройства, контекста, буферов, шейдеров и получения рендеринга вашего приложения через Direct3D. Документация ужасная, и это потребует некоторой пробной и пробной ошибки, но это не так плохо, как кажется. См. Здесь для маленького реального мира [18-мегапиксельная загрузка] (http://www.gigasoft.com) включает в себя WPF WinForm и MFC, а также его главным образом данные WAV и ГИС. – Robert

ответ

1

Позвольте мне попытаться перечислить плюсы и минусы каждого подхода - что, возможно, даст вам некоторое представление о том, что использовать.

GDI Pros

  • Легко рисовать векторные фигуры с
  • Нет необходимости включать дополнительные библиотеки

GDI Cons

  • Медленнее, чем DX
  • нужно ограничить «причудливый» рисунок (градиенты и т. п.), или он IGHT замедлить ход событий
  • Если схема должна быть интерактивными - не может быть отличным вариантом

SlimDX Pros

  • Можно сделать некоторые фантазии рисунок в то же время быстрее, чем GDI
  • Если рисунок является интерактивным - этот подход будет намного лучше
  • Поскольку вы рисуете примитивы, вы можете контролировать качество с каждым уровнем масштабирования

SlimDX Против

  • Не очень легко рисовать простые фигуры с - вам нужно написать свои собственные абстракции или использовать библиотеку, которая поможет вам рисовать фигуры
  • не так просто использовать GDI, особенно если вы не использовали его до

И, возможно, больше я забыл поставить здесь, но, возможно, это будет сделано для начала?

-A.

+0

Спасибо за ваш ответ! Есть ли у вас опыт использования SlimDX (интеграция wpf)? Есть ли верхний предел количества вещей, которые он может отобразить? Я пытаюсь взвесить кривую обучения SlimDX с преимуществами производительности, которые она предлагает против маршрута GDI. – CBent

+0

Я считаю, что SlimDX имеет образец взаимодействия WPF (http://code.google.com/p/slimdx/source/browse/trunk/samples/Direct3D10/WpfSample10/). Кроме того, несмотря на отсутствие верхнего предела для того, что может отображать SlimDX/DirectX, помните, что производительность - это только функция графической карты и эффективность рендеринга - на самом деле это справедливо как для GDI, так и для DX. Я бы порекомендовал сначала спуститься по маршруту GDI и взять репозиторий SlimDX, если производительность не соответствует вашим потребностям. – Ani

+0

Мне любопытно, почему вы рекомендуете использовать «GDI» для работы над SlimDX. Является ли кривая обучения SlimDX высокой?Существует опасение, что реализация способа GDI (рендеринг, быстрый пространственный выбор и интеграция) только для того, чтобы найти, что он слишком медленный, будет «пустой» временем, когда вы будете использовать ускоренный маршрут GPU, в первую очередь решит проблему , Опять же, спасибо за ответ. – CBent

7

Я использую GDI для своих cartographic application. В то время как GDI + медленнее, чем, скажем, DirectX, я нахожу, что есть много вещей и трюков, которые можно использовать для ускорения работы. Для подготовки данных используется большое количество процессора, прежде чем рисовать его, поэтому GDI не должен быть единственным узким местом.

Вещи, которые нужно посмотреть (и это достаточно, чтобы применить к другим графическим двигателям вообще, тоже):

  1. Прежде всего: меру. Используйте профилировщик, чтобы узнать, что является настоящим узким местом в вашем коде.
  2. Reuse GDI примитивы. Это очень важно. Если вам нужно нарисовать 100 000 графических объектов, которые выглядят одинаково или похожими, используйте те же самые Pen, Brush и т. Д. Создание этих примитивов дорого.
  3. Кэш данных визуализации - например: не пересчитывайте позиции элементов gfx, если вам это не нужно.
  4. При панорамировании/масштабировании нарисуйте сцену с ниже GDI + качество (и без дорогостоящих операций GDI). Есть несколько настроек объекта Graphics, чтобы снизить качество. После того, как пользователь прекратит панорамирование, нарисуйте сцену с высоким качеством.
  5. Много и много мелочей, которые улучшают производительность. Я разрабатываю это приложение уже 2-3 года (или это уже 4 хм?), И я все еще нахожу способы улучшить вещи :). Вот почему важно профилирование - изменение кода, и это может повлиять на производительность, поэтому вам нужно профайл нового кода.

Еще одна вещь: я не использовал SlimDX, но я попробовал Direct2D (я имею в виду Microsoft.WindowsAPICodePack.DirectX.Direct2D1). Производительность была значительно быстрее, чем GDI + в моем случае, но у меня были некоторые проблемы с рендерингом растровых изображений и у меня не было времени найти правильное решение.

+0

Руководитель проекта опасается идти по маршруту GDI +/Bitmap из-за того, что его прошлый опыт работы был медленным (он может быть прав или не прав). Он желает решения, основанного на производительности, и его застрял в голове, что DirectX - это решение. Считаете ли вы, что GDI + будет достаточно быстрым для 30 кадров в секунду и интерактивным с объектами 100k? – CBent

+0

@CBent: Трудно сказать, что это очень зависит от характера того, что вы рисуете (и, очевидно, оборудования). Но вот что-то я просто наткнулся на себя и окончательно экспериментирую для своего приложения: http://code.google.com/p/sharpdx/. Заявляет, что это самая быстрая управляемая библиотека DirectX - если она быстрее, чем WindowsAPICodePack, то это действительно очень быстро! –

+0

@CBent: и да, DirectX, как правило, подходит, когда вам нужна быстрая графика, поэтому я думаю, что мышление вашего руководителя проекта правильно. Я пошел с маршрутом GDI +, потому что он был моно-переносным - у меня есть пользователи, которые запускают мое приложение на Linux и Mac. –

3

Я недавно портировал код рисования на DirectX и был очень доволен результатами. В основном мы рисовали растровые изображения, используя бит-биение, и видим время визуализации, которое можно измерить в минутах, уменьшенном до 1-2 секунд.

Это не может сравниться с вами по-другому, поскольку мы перешли от бит-биения в C++ к Direct3D на C# с использованием SlimDX, но, я думаю, вы увидите преимущества производительности, даже если они не являются заказами как мы видим.

Я бы посоветовал вам взглянуть на использование Direct2D с помощью SlimDX. Вам нужно будет использовать DirectX 10.1, поскольку Direct2D по какой-то причине не совместим с DirectX 11. Если вы использовали API-интерфейс рисования в WPF, то вы уже будете знакомы с Direct2D, поскольку его API основан на API-интерфейсе WPF, насколько я могу судить. Основные проблемы с Direct2D - отсутствие документации и тот факт, что она работает только в Vista.

Я не экспериментировал с DirectX 10/WPF Interop, но я считаю, что это возможно (http://stackoverflow.com/questions/1252780/d3dimage-using-dx10)

EDIT: Я думал, 'дайте вам сравнение с нашим кодом рисования простого многоугольника. Первая версия WPF:

 StreamGeometry geometry = new StreamGeometry(); 

     using (StreamGeometryContext ctx = geometry.Open()) 
     { 
      foreach (Polygon polygon in mask.Polygons) 
      { 
       bool first = true; 

       foreach (Vector2 p in polygon.Points) 
       { 
        Point point = new Point(p.X, p.Y); 

        if (first) 
        { 
         ctx.BeginFigure(point, true, true); 
         first = false; 
        } 
        else 
        { 
         ctx.LineTo(point, false, false); 
        } 
       } 
      } 
     } 

Теперь версия Direct2D:

 Texture2D maskTexture = helper.CreateRenderTexture(width, height); 

     RenderTargetProperties props = new RenderTargetProperties 
     { 
      HorizontalDpi = 96, 
      PixelFormat = new PixelFormat(SlimDX.DXGI.Format.Unknown, AlphaMode.Premultiplied), 
      Type = RenderTargetType.Default, 
      Usage = RenderTargetUsage.None, 
      VerticalDpi = 96, 
     }; 

     using (SlimDX.Direct2D.Factory factory = new SlimDX.Direct2D.Factory()) 
     using (SlimDX.DXGI.Surface surface = maskTexture.AsSurface()) 
     using (RenderTarget target = RenderTarget.FromDXGI(factory, surface, props)) 
     using (SlimDX.Direct2D.Brush brush = new SolidColorBrush(target, new SlimDX.Color4(System.Drawing.Color.Red))) 
     using (PathGeometry geometry = new PathGeometry(factory)) 
     using (SimplifiedGeometrySink sink = geometry.Open()) 
     { 
      foreach (Polygon polygon in mask.Polygons) 
      { 
       PointF[] points = new PointF[polygon.Points.Count()]; 
       int i = 0; 

       foreach (Vector2 p in polygon.Points) 
       { 
        points[i++] = new PointF(p.X * width, p.Y * height); 
       } 

       sink.BeginFigure(points[0], FigureBegin.Filled); 
       sink.AddLines(points); 
       sink.EndFigure(FigureEnd.Closed); 
      } 

      sink.Close(); 
      target.BeginDraw(); 
      target.FillGeometry(geometry, brush); 
      target.EndDraw(); 
     } 

Как вы можете видеть, версия Direct2D немного больше работы (и опирается на несколько вспомогательных функций, которые я написал), но это на самом деле очень похоже.

+0

Я надеюсь, что, перейдя на версию DirectX (в настоящее время глядя на SharpDX), рендеринг нашего приложения будет улучшаться так же, как и ваш. Мы рисуем простые линии и двумерные многоугольники (но многие из них, которые WPF начинает задыхаться). Какие ресурсы вы использовали для исследований SlimDX? – CBent

+0

Я боюсь, что это было сделано год назад, поэтому я не могу вспомнить точные ресурсы, которые я использовал. SlimDX довольно хорошо подходит к API-интерфейсу Direct2D, поэтому любые примеры на C++ могут быть легко конвертированы в C#/SlimDX, что я и считаю. – Grokys

+0

Вау! Я только что получил отредактированный пост с включенным кодом. Они очень похожи. Вам нужно было изменить любой из ваших полигональных форматов, чтобы сделать их совместимыми для SlimDX? Является ли ваше приложение полноэкранным приложением, одной поверхностью DX или у вас есть сразу несколько поверхностей? – CBent