Почему бы не использовать GDI для повторного заполнения окна данными RGB из массива? - PullRequest
14 голосов
/ 09 ноября 2010

Это продолжение этого вопроса . В настоящее время я пишу простую игру и ищу самый быстрый способ (многократно) отображать массив данных RGB в окне Win32 без мерцания и других артефактов.

В ответах на предыдущий вопрос было рекомендовано несколько разных подходов, но не было единодушия относительно того, какой из них будет самым быстрым. Итак, я собрал тестовую программу. Код просто отображает кадровый буфер на экране несколько раз, как можно быстрее.

Вот результаты, которые я получил для 32-битных данных, работающих в режиме 32-битного видео - они могут удивить некоторых людей:

- Direct3D (1):             500 fps
- Direct3D (2):             650 fps
- DirectDraw (3):          1100 fps
- DirectDraw (4):           800 fps
- GDI (SetDIBitsToDevice): 2000 fps

Учитывая эти цифры:

  • Почему многие люди непреклонны, что GDI просто слишком медленный для этой операции?
  • Есть ли основания предпочитать DirectDraw или Direct3D над SetDIBitsToDevice?

Вот краткое изложение вызовов, сделанных каждым из прямых * кодовых путей. Если кто-нибудь знает более эффективный способ использования DirectDraw / Direct3D, пожалуйста, прокомментируйте.

1. CreateTexture(D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT);
       LockRect(); memcpy(); UnlockRect(); DrawPrimitive()

2. CreateTexture(0, D3DPOOL_SYSTEMMEM); CreateTexture(0, D3DPOOL_DEFAULT);
       LockRect(); memcpy(); UnlockRect(); UpdateTexture(); DrawPrimitive()

3. CreateSurface(); SetSurfaceDesc(lpSurface = &frameBuffer[0]);
       memcpy(); primarySurface->Blt();

4. CreateSurface();
       Lock(); memcpy(); Unlock(); primarySurface->Blt();

Ответы [ 3 ]

6 голосов
/ 09 ноября 2010

Здесь нужно иметь в виду несколько вещей.Прежде всего, многие «общие знания» основаны на некоторых фактах, которые на самом деле больше не применяются.

Во времена AGP, когда процессор общался непосредственно с графическим процессором, он всегда использовал базовый протокол PCI.что происходило со скоростью 1x (всегда и неизбежно).Только AGX 2x / 4x / 8x применяется, когда графический процессор напрямую подключается к контроллеру памяти .Другими словами, в зависимости от , когда вы смотрели , графический процессор загружал текстуру из памяти в 8 раз быстрее, чем центральный процессор для отправки тех же данных непосредственно в графический процессор.Конечно, процессор также имел значительно большую пропускную способность для памяти, чем поддерживаемая шина PCI.

Однако, когда все переключилось на PCI-E, это полностью изменилось.Хотя могут быть различия в пропускной способности в зависимости от пути, нет общего правила, что память-> GPU будет быстрее, чем CPU-> GPU.Единственное обобщение, которое (в основном) безопасно, состоит в том, что , если у вас есть выделенная графическая карта, то у GPU почти всегда будет больше пропускной способности памяти на видеокарте, чем основной памяти на материнской плате.

В вашем случае это не имеет большого значения - вы говорите о перемещении данных из пространства ЦП в пространство GPU независимо.Основная разница в скорости при использовании DirectX (или OpenGL) возникает, когда вы сохраняете все (или большую часть) вычислений на графическом процессоре и вообще не используете процессор (или основную память).Они не (теперь, когда AGP является историей) не обеспечивают какого-либо существенного улучшения памяти-> пропускной способности дисплея.

2 голосов
/ 09 ноября 2010

Джерри Коффин делает несколько хороших замечаний.Следует помнить, что DI обозначает в SetDIBitsToDevice.Это означает, что устройство не зависит.Что означает, что вы всегда были во власти водителей.Некоторые драйверы были полностью мусором, и это сильно повлияло на производительность.DirectDraw также страдал от подобных проблем ... но у вас также был доступ к аппаратным блиттерам, так что это было в целом более полезно.IHV также имели тенденцию уделять больше времени написанию соответствующих драйверов для DirectDraw из-за его игровой ассоциации.Кто хочет быть в нижней части списка производительности, когда аппаратное обеспечение способно работать лучше?

В наши дни многие графические карты могут принимать битовые данные напрямую, поэтому преобразование не происходит.Если это действительно необходимо, то это НЕВЕРОЯТНО быстро и в наши дни.

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

Соедините это с тем фактом, что вы не проводите тестирование на лайки (с DDraw и D3D), создав текстуру/ Surface, блокировка, копирование, разблокировка, а затем рисование через задний буфер (различными способами).Чтобы добиться максимальной производительности, лучше всего напрямую заблокировать буфер, используя блокировку DISCARD, а затем непосредственно в возвращаемый буфер memcpy'а, прежде чем разблокировать.Это значительно приблизит вашу производительность к SetDIBitsToDevice.Однако я все же ожидал бы, что D3D будет медленнее, чем DDraw, по причинам, изложенным выше.

1 голос
/ 09 ноября 2010

Причина, по которой вы услышите беспокойство людей о GDI, заключается в том, что раньше это были просто вызовы Windows API.Более новые его версии (которые назывались GDI +, когда я в последний раз смотрел на них) на самом деле представляют собой просто API, размещенный поверх вызовов DirectX.Поэтому использование GDI может показаться довольно простым в программировании, но добавление слоя между вещами всегда замедляет работу.Как упоминалось в ответе Джерри Коффина, ваши примеры касаются перемещения данных, и это медленное время.Я немного удивлен тем, что DirectX намного медленнее, но я не могу больше помочь с копанием документации по DirectX (которая была довольно крутой в течение довольно долгого времени на самом деле). Возможно, стоит проверить www.codesampler.comЯ всегда находил у него хорошие стартовые места, и на самом деле, хотя я могу быть безумен за эти слова, я бы поклялся, что улучшения в DirectX SDK в документации, и примеры были сделаны на основе этой работы, ребята!)

Что касается обсуждения DirectDraw против Direct3D (а не вызовов GDI).Я бы сказал, перейти к Direct3D.Я считаю, что DirectDraw устарела с 8.0 или около того, а 9.0 существует уже довольно давно.И, в конце концов, весь DirectX - это 3D, он просто варьируется в зависимости от уровня полезного 2D-интерфейса, который есть вокруг, но вы можете обнаружить, что вы можете делать очень интересные вещи в 2D-среде, когда фактически используете 3D-пространство.(У меня было довольно аккуратное случайно сгенерированное оружие молнии для клона космических захватчиков:))

В любом случае, надеюсь, это помогло!

PS: Следует отметить, что DirectX не всегдасамый быстрый.Для ввода с клавиатуры (если это не изменилось в 10 или 11) почти всегда рекомендовалось использовать события Windows ... поскольку DirectInput был просто оберткой для этой системы! .. Однако XInput - -wesome - !!

...