[GDI] Узкое место - StretchBlt. Возможна ли альтернатива?
От: spbAngel  
Дата: 07.11.06 09:47
Оценка:
Во время выполнения программы, приходится вызывать функцию StretchBlt. В среднем, около 100-120 раз в секунду. Задача алгоритма — пропорциональный scaling некоторых изображений с выводом результата на экран (в данном случае — в окно).

Оцените, pls, код. И подскажите, какие есть альтернативы. В StretchBlt не устраивает скорость и "ступенчатость" (по-моему, это называется "ближайший цвет" — отсутствие сглаживания)

HWND iHwnd;
int mCount;
int mCountOfScale;
RECT[] mDestRect;
HDC[] mSrcBitmapDC;
int[] mSrcBitmapWidth;
int[] mSrcBitmapHeight;
float mScale;
case WM_PAINT:
    int lWidth = 1024;
    int lHeight = 738;
    PAINTSTRUCT lPS;
    
    HDC lWindowDC = ::BeginPaint(iHwnd, &lPS);
    HDC lBitmapDC = ::CreateCompatibleDC(lWindowDC);
    HBITMAP lBitmap = ::CreateCompatibleBitmap(lWindowDC, lWidth, lHeight);
    HGDIOBJ lNullBitmap = ::SelectObject(lBitmapDC, lBitmap);    
    for (int j = 0; j < mCount; j++)
    {
        ::StretchBlt(
            lBitmapDC,                                      // dest DC - tempory image
            mDestRect[j].left, mDestRect[j].top,            // position for drawing
            mSrcBitmapWidth[j] * ьScale,                    // needed width of image
            mSrcBitmapHeight[j] * mScale,                   // needed height of image
            mSrcBitmapDC[j],                                // src DC - image
            0, 0,  mSrcBitmapWidth[j], mSrcBitmapHeight[j], // size of source image
            SRCCOPY);
    }
    ::BitBlt(lWindowDC, 0, 0, lWidth, lHeight, lBitmapDC, 0, 0, SRCCOPY);
    ::SelectObject(lBitmapDC, lNullBitmap);
    ::DeleteDC(lBitmapDC);
    ::DeleteObject(lBitmap);
    ::EndPaint(iHwnd, &lPS);
    break;

Примечания:
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>

07.11.06 13:45: Перенесено модератором из 'WIN API' — Odi$$ey
Re: [GDI] Узкое место - StretchBlt. Возможна ли альтернатива
От: NightBlade Россия  
Дата: 07.11.06 10:30
Оценка:
A>Оцените, pls, код. И подскажите, какие есть альтернативы. В StretchBlt не устраивает скорость и "ступенчатость" (по-моему, это называется "ближайший цвет" — отсутствие сглаживания)

SetStretchBltMode — есть такая функция. переключает режим масштабирования, сглаживание в этом списке присутствует под именем HALFTONE (только в линейке NT). тормозит еще сильнее, естественно

в данном случае StretchBlt выполняется в памяти, GDI тут поступает чисто софтово, отсюда тормоза. видеокарта убыстряет растровые операции при переносе видеопамять-видеопамять, и, МОЖЕТ БЫТЬ, оперативка-видеопамять.

а нельзя картинку отрендерить один раз, а потом показывать по WM_PAINT обычным BitBlt?
Все вопросы на nightblade@inbox.ru
Re: [GDI] Узкое место - StretchBlt. Возможна ли альтернатива
От: Аноним  
Дата: 07.11.06 10:58
Оценка:
Здравствуйте, spbAngel, Вы писали:

A>Во время выполнения программы, приходится вызывать функцию StretchBlt. В среднем, около 100-120 раз в секунду. Задача алгоритма — пропорциональный scaling некоторых изображений с выводом результата на экран (в данном случае — в окно).

SetStretchBltMode

A зачем 100-120 раз в секунду, если даже для фильма 30 раз вполне достаточно? И каждый раз именно Stretch?
Re: [GDI] Узкое место - StretchBlt. Возможна ли альтернатива
От: Plague Россия  
Дата: 07.11.06 13:07
Оценка:
Судя по моему предыдущему опыту, подобные критические функции я просто переписывал вручную, что всегда давало серьезный прирост производительности.
Просто для стандартных RGBA использовать свою отрисовку, а для всяких "нестандартных" — _стандартную_.

Учитывая, что отрисовка чисто софтварная, то можно реализовать софтварный мип-маппинг иль еще чего наворотить, но это никому ненужный изврат, зато не будет ступенчатости .
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: [GDI] Узкое место - StretchBlt. Возможна ли альтернат
От: spbAngel  
Дата: 07.11.06 16:05
Оценка:
Здравствуйте, NightBlade, Вы писали:

A>>Оцените, pls, код. И подскажите, какие есть альтернативы. В StretchBlt не устраивает скорость и "ступенчатость" (по-моему, это называется "ближайший цвет" — отсутствие сглаживания)


NB>SetStretchBltMode — есть такая функция. переключает режим масштабирования, сглаживание в этом списке присутствует под именем HALFTONE (только в линейке NT). тормозит еще сильнее, естественно


Спасибо. Попробую.

NB>в данном случае StretchBlt выполняется в памяти, GDI тут поступает чисто софтово, отсюда тормоза. видеокарта убыстряет растровые операции при переносе видеопамять-видеопамять, и, МОЖЕТ БЫТЬ, оперативка-видеопамять.


Не подскажите, как с этим можно использовать? Как загружать рисунки в видеопамять?

NB>а нельзя картинку отрендерить один раз, а потом показывать по WM_PAINT обычным BitBlt?


К сожалению, нет. Исходные рисунки и конечные положения на рисунке постоянно меняются.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: [GDI] Узкое место - StretchBlt. Возможна ли альтернат
От: spbAngel  
Дата: 07.11.06 16:05
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Здравствуйте, spbAngel, Вы писали:


A>>Во время выполнения программы, приходится вызывать функцию StretchBlt. В среднем, около 100-120 раз в секунду. Задача алгоритма — пропорциональный scaling некоторых изображений с выводом результата на экран (в данном случае — в окно).

А>SetStretchBltMode

А>A зачем 100-120 раз в секунду, если даже для фильма 30 раз вполне достаточно? И каждый раз именно Stretch?


Именно Stretch. Около 20-25 раз в секунду, около 5-10 (до 20) рисунков за раз.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: [GDI] Узкое место - StretchBlt. Возможна ли альтернатива
От: spbAngel  
Дата: 08.11.06 09:35
Оценка:
Здравствуйте, spbAngel, Вы писали:

В этой ветке
Автор: Multy
Дата: 08.08.06
обсуждалось, можно ли ускорить BitBlt. Были предположения, что для изменения размеров, может быть выгодней использовать DrawDibDraw
Автор:
Дата: 20.09.06
. Хотя, по этому поводу, критически высказывались некоторые люди. Имеет ли смысл проверять? И заменить StretchBlt на DrawDibDraw?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: [GDI] Узкое место - StretchBlt. Возможна ли альтернат
От: NightBlade Россия  
Дата: 08.11.06 10:19
Оценка: 2 (1)
NB>>в данном случае StretchBlt выполняется в памяти, GDI тут поступает чисто софтово, отсюда тормоза. видеокарта убыстряет растровые операции при переносе видеопамять-видеопамять, и, МОЖЕТ БЫТЬ, оперативка-видеопамять.

A>Не подскажите, как с этим можно использовать? Как загружать рисунки в видеопамять?


под видеопамятью в данном случае я подразумевал видеобуфер, т.е. экран, т.е. самая быстрая отрисовка — из одного видимого окна в другое видимое окно (или из одной части окна в другое)
в данном случае это не поможет
для загрузки изображений в память видеокарты (текстур, например) требуется использование DirectX

как более быструю альтернативу могу предложить использовать DirectDraw или группу функций DrawDib
Все вопросы на nightblade@inbox.ru
Re[2]: [GDI] Узкое место - StretchBlt. Возможна ли альтернат
От: Andrew S Россия http://alchemy-lab.com
Дата: 08.11.06 10:41
Оценка: 2 (1)
A>В этой ветке
Автор: Multy
Дата: 08.08.06
обсуждалось, можно ли ускорить BitBlt. Были предположения, что для изменения размеров, может быть выгодней использовать DrawDibDraw
Автор:
Дата: 20.09.06
. Хотя, по этому поводу, критически высказывались некоторые люди. Имеет ли смысл проверять? И заменить StretchBlt на DrawDibDraw?


Не имеет. Видимый прирост производительности _в_некоторых_ ситуациях обеспечивает только ручное написание блиттера. А обычно gdi даже быстрее.

Теперь, что надо делать вам.
1. Вынести создание совместимого контекста и битмапа за пределы paint — пусть живет всегда (соответственно, пересоздавать при изменении режимов, для чего обрабатывать соотв. сообщение). Попробовать — если производительнсть устроит — отлично. В большинстве нормальных драйверов тут используется аппаратный блиттер, поэтому даже написав функции стретча вручную, сравнимой производительности не достигнуть.
2. Попробовать использовать dib секции вместо совместимого битмапа, либо обычные DIB.

А вообще — 100 фпс при помощи или без gdi — довольно нетривиально. Учитывая, что один экран это по меньшей мере 4 мб данных + затраты на скалинг.. Имхо, без аппаратной поддержки тут не обойтись.
Может, direct3d посмотреть?
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[3]: [GDI] Узкое место - StretchBlt. Возможна ли альтернат
От: spbAngel  
Дата: 10.11.06 08:57
Оценка:
Здравствуйте, Andrew S, Вы писали:

AS>Может, direct3d посмотреть?


Спасибо. На днях понял, что это вполне подходящий вариант (Direct3D для отрисовки 2D — не мог привыкнуть) и дописываю уже прототип. За одно и DirectX изучу...
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[4]: [GDI] Узкое место - StretchBlt. Возможна ли альтернат
От: spbAngel  
Дата: 10.11.06 08:58
Оценка:
Здравствуйте, NightBlade, Вы писали:

NB>для загрузки изображений в память видеокарты (текстур, например) требуется использование DirectX


NB>как более быструю альтернативу могу предложить использовать DirectDraw или группу функций DrawDib


Насколько я помню, DirectDraw отсутствует уже в 8-ой версии DirectX. Сейчас пишу прототип на Direct3D. Или я неправ? Просто Direct3D для решения 2D-задачи... Просто непривычно.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[5]: [GDI] Узкое место - StretchBlt. Возможна ли альтернат
От: Сергей  
Дата: 10.11.06 10:01
Оценка:
Здравствуйте, spbAngel, Вы писали:

A>Насколько я помню, DirectDraw отсутствует уже в 8-ой версии DirectX. Сейчас пишу прототип на Direct3D. Или я неправ? Просто Direct3D для решения 2D-задачи... Просто непривычно.


Direct3D для 2D задачи — вполне нормальное явление. Ибо так можно задействовать мощь аппаратного ускорения современных видеокарт.
Re[5]: [GDI] Узкое место - StretchBlt. Возможна ли альтернат
От: NightBlade Россия  
Дата: 10.11.06 10:07
Оценка:
A>Насколько я помню, DirectDraw отсутствует уже в 8-ой версии DirectX. Сейчас пишу прототип на Direct3D. Или я неправ? Просто Direct3D для решения 2D-задачи... Просто непривычно.

DirectX любой версии тащит за собой все предыдущие, для совместимости
Все вопросы на nightblade@inbox.ru
Re[6]: [GDI] Узкое место - StretchBlt. Возможна ли альтернат
От: spbAngel  
Дата: 10.11.06 13:16
Оценка:
Здравствуйте, NightBlade, Вы писали:

A>>Насколько я помню, DirectDraw отсутствует уже в 8-ой версии DirectX. Сейчас пишу прототип на Direct3D. Или я неправ? Просто Direct3D для решения 2D-задачи... Просто непривычно.


NB>DirectX любой версии тащит за собой все предыдущие, для совместимости


Думаете, стОит использовать именно DirectDraw? Понимаю, что логичней, но... Не могу сформулировать в вопрос чувства. Как-никак 7-ая версия...
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[7]: [GDI] Узкое место - StretchBlt. Возможна ли альтернат
От: Andrew S Россия http://alchemy-lab.com
Дата: 10.11.06 13:20
Оценка: 2 (1)
A>>>Насколько я помню, DirectDraw отсутствует уже в 8-ой версии DirectX. Сейчас пишу прототип на Direct3D. Или я неправ? Просто Direct3D для решения 2D-задачи... Просто непривычно.

NB>>DirectX любой версии тащит за собой все предыдущие, для совместимости


A>Думаете, стОит использовать именно DirectDraw? Понимаю, что логичней, но... Не могу сформулировать в вопрос чувства. Как-никак 7-ая версия...


Нет, не стОит. Там практически не поддерживается аппаратное ускорение, даже для блиттера (по-крайней мере, я для себя в свое время такие выводы сделал, потестировав производительность блиттинга директдрава и gdi). Почти все современные 2d игрушки используют direct3d.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[8]: [GDI] Узкое место - StretchBlt. Возможна ли альтернат
От: spbAngel  
Дата: 10.11.06 13:26
Оценка:
Здравствуйте, Andrew S, Вы писали:

A>>Думаете, стОит использовать именно DirectDraw? Понимаю, что логичней, но... Не могу сформулировать в вопрос чувства. Как-никак 7-ая версия...


AS>Нет, не стОит. Там практически не поддерживается аппаратное ускорение, даже для блиттера (по-крайней мере, я для себя в свое время такие выводы сделал, потестировав производительность блиттинга директдрава и gdi). Почти все современные 2d игрушки используют direct3d.


Благодарю. Выполненные тесты и мнение опытного разработчика — то что было надо. Буду копать в сторону Direct3D
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[9]: [GDI] Узкое место - StretchBlt. Возможна ли альтернат
От: Sapersky  
Дата: 10.11.06 15:10
Оценка: 3 (1)
Здравствуйте, spbAngel, Вы писали:

A>Здравствуйте, Andrew S, Вы писали:


A>>>Думаете, стОит использовать именно DirectDraw?

AS>>Нет, не стОит. Там практически не поддерживается аппаратное ускорение, даже для блиттера (по-крайней мере, я для себя в свое время такие выводы сделал, потестировав производительность блиттинга директдрава и gdi). Почти все современные 2d игрушки используют direct3d.

Видимо во времена ваших тестов самыми распространёнными картами были S3 Trio
AFAIK, DirectDraw умеет делать stretch с фильтрацией на большинстве современных и не очень видеокарт (начиная где-то с TNT).
Хотя у некоторых карт есть специфические особенности, например, у Radeon'ов (по крайней мере 9000'ой серии) размер поверхности, с которой можно делать stretch, ограничен максимальным размером текстуры (видимо, ATI'шники реализовали stretch через наложение текстуры; у NVidia всё "по-честному", размер поверхности ограничен только объёмом видеопамяти). Похожие проблемы у интегрированного видео на i915 — там при превышении макс. размера текстуры всё начинает сильно тормозить. На старом интегрированном видео (i810, i815 и вроде i845) аппаратный stretch через DirectDraw не работает, хотя текстуры накладывать они могут.

В D3D ограничение на размер текстуры официальное, т.е. больше — однозначно нельзя. Обычный макс. размер для карты "средней устарелости" (ранние GeForce, Radeon) — 2048 * 2048.

А игрушки используют D3D главным образом для спецэффектов вроде полупрозрачности, поворота картинки и т.п. Этого в DirectDraw действительно нет.
Re[10]: [GDI] Узкое место - StretchBlt. Возможна ли альтерна
От: Andrew S Россия http://alchemy-lab.com
Дата: 10.11.06 15:26
Оценка:
A>>>>Думаете, стОит использовать именно DirectDraw?
AS>>>Нет, не стОит. Там практически не поддерживается аппаратное ускорение, даже для блиттера (по-крайней мере, я для себя в свое время такие выводы сделал, потестировав производительность блиттинга директдрава и gdi). Почти все современные 2d игрушки используют direct3d.

S>Видимо во времена ваших тестов самыми распространёнными картами были S3 Trio


Видимо. Взгляните на интерфейсы DDI и DDDI — посмотрите, что мешает делать аппаратный стретч и в ddraw и в gdi одновременно? Поэтому, собственно, разницу между стретчем в ddraw и gdi найти будет трудно, если у разработчиков драйверов голова и руки были на месте.
А тестировалось это дело все на MX400. Я не претендую на полную объективность, отнюдь. Если у вас есть другие данные и они подтверждаются практикой — велкам, вам только спасибо скажут.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[10]: [GDI] Узкое место - StretchBlt. Возможна ли альтерна
От: spbAngel  
Дата: 10.11.06 15:30
Оценка:
Здравствуйте, Sapersky, Вы писали:

S>Здравствуйте, spbAngel, Вы писали:


A>>Здравствуйте, Andrew S, Вы писали:


A>>>>Думаете, стОит использовать именно DirectDraw?

AS>>>Нет, не стОит. Там практически не поддерживается аппаратное ускорение, даже для блиттера (по-крайней мере, я для себя в свое время такие выводы сделал, потестировав производительность блиттинга директдрава и gdi). Почти все современные 2d игрушки используют direct3d.

S>Видимо во времена ваших тестов самыми распространёнными картами были S3 Trio

S>AFAIK, DirectDraw умеет делать stretch с фильтрацией на большинстве современных и не очень видеокарт (начиная где-то с TNT).
S>Хотя у некоторых карт есть специфические особенности, например, у Radeon'ов (по крайней мере 9000'ой серии) размер поверхности, с которой можно делать stretch, ограничен максимальным размером текстуры (видимо, ATI'шники реализовали stretch через наложение текстуры; у NVidia всё "по-честному", размер поверхности ограничен только объёмом видеопамяти). Похожие проблемы у интегрированного видео на i915 — там при превышении макс. размера текстуры всё начинает сильно тормозить. На старом интегрированном видео (i810, i815 и вроде i845) аппаратный stretch через DirectDraw не работает, хотя текстуры накладывать они могут.

S>В D3D ограничение на размер текстуры официальное, т.е. больше — однозначно нельзя. Обычный макс. размер для карты "средней устарелости" (ранние GeForce, Radeon) — 2048 * 2048.


Respect. Когда-нибудь, и я буду такими данными делиться. А пока, вот сам узнаю. Глубоко копаешь.

S>А игрушки используют D3D главным образом для спецэффектов вроде полупрозрачности, поворота картинки и т.п. Этого в DirectDraw действительно нет.


Спасибо за инфу. Думается, что это может пригодится в будущем. Посему, всё таки остановим выбор на D3D.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[11]: [GDI] Узкое место - StretchBlt. Возможна ли альтерна
От: Аноним  
Дата: 10.11.06 17:44
Оценка:
Здравствуйте, Andrew S, Вы писали:

A>>>>>Думаете, стОит использовать именно DirectDraw?

AS>>>>Нет, не стОит. Там практически не поддерживается аппаратное ускорение, даже для блиттера (по-крайней мере, я для себя в свое время такие выводы сделал, потестировав производительность блиттинга директдрава и gdi). Почти все современные 2d игрушки используют direct3d.

S>>Видимо во времена ваших тестов самыми распространёнными картами были S3 Trio


AS>Видимо. Взгляните на интерфейсы DDI и DDDI — посмотрите, что мешает делать аппаратный стретч и в ddraw и в gdi одновременно? Поэтому, собственно, разницу между стретчем в ddraw и gdi найти будет трудно, если у разработчиков драйверов голова и руки были на месте.


Уточню: под аппаратным stretch я подразумеваю полностью аппаратный, с перемещением видеопамять->видеопамять. В случае системная->видео скорость, действительно, мало отличается от GDI. Похоже что DirectDraw в этом случае переключается на обычный StretchBlt.

В варианте видео->видео DirectDraw, по моим тестам, быстрее GDI в десятки-сотни раз. Stretch на весь экран занимает, как правило, меньше миллисекунды даже на старых картах. К тому же он делается с фильтрацией независимо от версии Windows (StretchBlt может фильтровать только в NT).

Фактически скорость получается примерно такая же, как и в D3D, да и по некоторым косвенным признакам (см. в предыдущем сообщении про Radeon) можно судить, что аппаратный stretch DirectDraw ближе к D3D, чем к GDI.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.