Почему бы не использовать GDI для многократного заполнения окна данными RGB из массива?
Это продолжение этого вопроса. В настоящее время я пишу простую игру и ищу самый быстрый способ (неоднократно) отображать массив данных 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?
Вот краткое изложение вызовов, сделанных каждой из кодеков Direct *. Если кто-либо знает более эффективный способ использования 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();
Ответы
Ответ 1
Здесь нужно иметь в виду пару вещей. Прежде всего, многие "общие знания" основаны на некоторых фактах, которые больше не применяются.
В дни AGP, когда CPU говорил напрямую с GPU, он всегда использовал базовый протокол PCI, который происходил со скоростью "1x" (всегда и неизбежно). AGX 2x/4x/8x применяется только тогда, когда графический процессор поступает непосредственно на контроллер памяти. Другими словами, в зависимости от того, когда вы смотрели, было бы в 8 раз быстрее, чтобы загрузка графического процессора была текстурой из памяти, как это было для CPU, чтобы отправлять те же данные непосредственно на GPU. Разумеется, процессор также имел большую пропускную способность в памяти, чем поддерживаемая PCI-шина.
Однако, когда все переключилось на PCI-E, это полностью изменилось. Хотя в зависимости от пути могут быть различия в пропускной способности, нет общего правила, согласно которому memory- > GPU будет быстрее, чем CPU- > GPU. Одно из обобщений, которое (в основном) безопасно, заключается в том, что если у вас есть выделенная видеокарта, то графический процессор почти всегда будет иметь большую пропускную способность для памяти на графической карте, чем в основной памяти на материнской плате.
В вашем случае это не имеет большого значения, хотя вы говорите о том, чтобы перемещать данные из пространства процессора в пространство GPU независимо. Основная разница в скорости с использованием DirectX (или OpenGL) происходит, когда вы сохраняете все (или большинство) вычислений на графическом процессоре и вообще не используете CPU (или основную память). Они не делают (теперь, когда AGP - это история) обеспечивают существенное улучшение пропускной способности памяти → .
Ответ 2
Джерри Коффин делает несколько хороших моментов. Дело в том, что DI стоит в SetDIBitsToDevice. Это означает Device Independent. Это означает, что вы ВСЕГДА были во власти водителей. Некоторые драйверы были полным мусором, и это сильно повлияло на производительность. DirectDraw также страдал от подобных проблем... но у вас также был доступ к аппаратным блиттерам, поэтому он был более полезен. IHV также, как правило, уделяли больше времени написанию надлежащих драйверов для DirectDraw из-за своей игровой ассоциации. Кто хочет быть нижней частью производительности, когда оборудование вполне способно сделать лучше?
В наши дни многие видеокарты могут принимать данные бит напрямую, поэтому никакого преобразования не происходит. Если это нужно, чтобы его запели, это также НЕВЕРОЯТНО быстро в этот день и возраст.
Причина, по которой ваша производительность Direct3D настолько ужасная, по сравнению с тем, что Direct3D, по своей природе, предназначен для использования полностью внутри GPU, использует нечетные и сложные форматы для повышения производительности кэша и т.д.
Пара, что с тем фактом, что вы не тестируете, как например (с DDraw и D3D), создавая текстуру/поверхность, блокируя ее, копируя, разблокируя, а затем рисуя задний буфер (с помощью различных методов). Чтобы получить максимальную производительность, вам лучше всего сразу заблокировать бэкбуффер, используя блокировку DISCARD, а затем memcpy'ing непосредственно в возвращенный буфер перед разблокировкой. Это значительно приблизит вашу производительность к SetDIBitsToDevice. Я все же ожидал бы, что D3D будет медленнее, чем DDraw, однако по причинам, изложенным выше.
Ответ 3
Причина, по которой вы будете слышать, что люди нажимают на GDI, заключается в том, что она использовалась только для вызовов окон Windows API. Более новые версии (называемые GDI +, когда я последний раз смотрел на em) на самом деле были просто API, размещенным поверх вызовов DirectX. Поэтому использование GDI может казаться довольно простым программированием порой, но добавление слоя между вещами всегда замедляет работу. Как упоминалось в ответе Джерри Коффина, ваши примеры касаются перемещения данных, и это медленное время. Я немного удивлен тем, что DirectX работает намного медленнее, но я не могу больше помочь с обработкой документации DirectX (которая была довольно удивительной в течение довольно долгого времени. Возможно, вы захотите проверить www.codesampler.com Я всегда находил хорошие стартовые места от него и на самом деле, хотя я могу быть сумасшедшим, чтобы сказать это, я поклялся в усовершенствованиях DirectX SDK в doc, и примеры были сделаны на основе этих парней!)
Что касается обсуждения DirectDraw vs Direct3D (а не GDI). Я бы сказал, пойти в Direct3D. Я считаю, что DirectDraw устарел с 8.0 или около того, а 9.0 существует довольно долго. И в конце концов, все DirectX - это 3D, он просто меняется на уровнях полезной 2D-авиты, которые находятся вокруг, но вы можете обнаружить, что в 2D-среде вы можете делать очень интересные вещи, когда вы фактически используете 3D-пространство. (У меня было довольно аккуратное случайно созданное молниеносное оружие для клонирования космических захватчиков за один раз:))
Anywho, надеюсь, что это помогло!
PS: Следует отметить, что DirectX не всегда самый быстрый. Для ввода с клавиатуры (если это не изменилось в 10 или 11), почти всегда было рекомендовано использовать события Windows. Поскольку DirectInput на самом деле был просто оболочкой для этой системы!.. XInput, однако, является -awesome -!!