A>>>>>>Думаете, стОит использовать именно DirectDraw? AS>>>>>Нет, не стОит. Там практически не поддерживается аппаратное ускорение, даже для блиттера (по-крайней мере, я для себя в свое время такие выводы сделал, потестировав производительность блиттинга директдрава и gdi). Почти все современные 2d игрушки используют direct3d.
S>>>Видимо во времена ваших тестов самыми распространёнными картами были S3 Trio
AS>>Видимо. Взгляните на интерфейсы DDI и DDDI — посмотрите, что мешает делать аппаратный стретч и в ddraw и в gdi одновременно? Поэтому, собственно, разницу между стретчем в ddraw и gdi найти будет трудно, если у разработчиков драйверов голова и руки были на месте.
А>Уточню: под аппаратным stretch я подразумеваю полностью аппаратный, с перемещением видеопамять->видеопамять. В случае системная->видео скорость, действительно, мало отличается от GDI. Похоже что DirectDraw в этом случае переключается на обычный StretchBlt.
О как. А про то, что DDB вполне себе могут жить в видеопамяти, вы подумали? Интерфейс DDI\gdi вполне позволяет такие вещи, более того, он на них и ориентирован. Например, на моей машине блиттинг ddb-ddb (или ddb-ScreenDC) занимает в разы меньше времени, чем оный же для ddb-dib. При этом вызовы gdi вполне себе буферизируются, поэтому суммарная производительность вполне и вполне, опять же, при учете нормальных драйверов.
Думаю, вполне очевидно, что DDB в данном случае расположен в видеопамяти — указанную пропускную способность (почти 7.5 гб\с) системная память на моей машине не обеспечивает.
А>В варианте видео->видео DirectDraw, по моим тестам, быстрее GDI в десятки-сотни раз. Stretch на весь экран занимает, как правило, меньше миллисекунды даже на старых картах. К тому же он делается с фильтрацией независимо от версии Windows (StretchBlt может фильтровать только в NT).
Ок, возможно. По крайней мере, результаты для bitblt и stretchblt у меня для gdi отличались в разы. Приведете тесты?
А>Фактически скорость получается примерно такая же, как и в D3D, да и по некоторым косвенным признакам (см. в предыдущем сообщении про Radeon) можно судить, что аппаратный stretch DirectDraw ближе к D3D, чем к GDI.
Все зависит от реализации. DDI предоставляет разработчикам полные возможности по аппаратному ускорению стретча в gdi. Я встречал реализации, где блиттинг в ddraw вообще не ускорялся, судя по ощущениям. (i740, такой обрезок, если помните)
Здравствуйте, Andrew S, Вы писали:
AS>О как. А про то, что DDB вполне себе могут жить в видеопамяти, вы подумали? Интерфейс DDI\gdi вполне позволяет такие вещи, более того, он на них и ориентирован. Например, на моей машине блиттинг ddb-ddb (или ddb-ScreenDC) занимает в разы меньше времени, чем оный же для ddb-dib. При этом вызовы gdi вполне себе буферизируются, поэтому суммарная производительность вполне и вполне, опять же, при учете нормальных драйверов.
Про DDB знаю. Но от применения отпугивало вот это самое "могут жить" (в DirectDraw, если указал в видео — 99% будет в видео); отсуствие каких-либо эффектов, даже примитивного цветового ключа; и ещё некоторые странные побочные эффекты вроде "остановки времени", т.е. замеряемое QueryPerformanceCounter время блиттинга стремится к 0, хотя при большом количестве циклов невооружённым глазом видно, что оно явно не нулевое. Причём не только я с этим сталкивался. Не знаете, как это можно объяснить (не принципом же относительности Эйнштейна ?
А>>В варианте видео->видео DirectDraw, по моим тестам, быстрее GDI в десятки-сотни раз. Stretch на весь экран занимает, как правило, меньше миллисекунды даже на старых картах. К тому же он делается с фильтрацией независимо от версии Windows (StretchBlt может фильтровать только в NT). AS>Ок, возможно. По крайней мере, результаты для bitblt и stretchblt у меня для gdi отличались в разы. Приведете тесты?
Тест (exe): http://slil.ru/23397272
Могу и исходники выложить (Delphi), но ничего сложного там нет — создаётся первичная поверхность, клиппер, поверхность с картинкой (в качестве картинки — снимок рабочего стола). Картинке делается Blt на экран безо всяких задних буферов.
AS> Все зависит от реализации. DDI предоставляет разработчикам полные возможности по аппаратному ускорению стретча в gdi. Я встречал реализации, где блиттинг в ddraw вообще не ускорялся, судя по ощущениям. (i740, такой обрезок, если помните)
i740 — это скорее "первый блин комом" Так что кривость драйверов неудивительна.
И даже если DirectDraw не ускоряется — то во всяком случае он не медленнее GDI/DDB, так? A вот наоборот — легко, например, DDB на Radeon 9000 + Win98 тормозит сильнее DIB.
Впрочем, здесь я сам начинаю увлекаться седой стариной. Лучше было бы подумать о Висте, применительно к которой это обсуждение вообще будет бессмысленным, по причине реализации GDI через D3D.
Re: [GDI] Узкое место - StretchBlt. Возможна ли альтернатива
Советую перейти на ренедринг OpenGL.
У меня есть опыт рендеринта с масштабированием огромных рисунков через DirectX, OpenGL, GDI и GDI+.
GDI+ тормозит всегда, даже на простейших операциях. То есть вообще всегда. Любая серьёзная графика на GDI+ это слайд-шоу. GDI тормозит иногда, но в целом масштабирование почти всегда грузит процессор на 100%. В отличие от предыдущих вариантов, DirectX это хорошо в плане скорости, даже очень хорошо. Первая же моя программа с прокруткой и масштабированием так и не смогла загрузить процессор больше чем на 5%, и то небось оконными сообщениями. OpenGL порой несколько медленее, но у OpenGL есть ряд серьёзных преимуществ для "не игр". Во-первых, OpenGL не надо распространять, она всегда есть. У меня программа на DirectX9 отказывалась запускатся на голой Windows 2000 SP4 (что вобщем-то нормально). Для тестирования на "плохих" видеокартах я запускал программу внутри VMWare — практически дохлый номер запустить там DirectX. С OpenGL ситуация прямо противоположная — программа запустилась на Windows 2000 SP4 внутри VMWare без проблем. Наблюдались только небольшие артефакты текстурирования, а в целом всё вполне прилично, включая (тут я был в шоке) производительность. Во-вторых, OpenGL не навязывает способ хранения данных, не принуждая к созданию разного рода буферов вершин. В-третьих, OpenGL поддерживает отрисовку квадратов (glBegin(GL_QUADS)). Вобщем советую.
Здравствуйте, adontz, Вы писали:
A>Здравствуйте, spbAngel, Вы писали:
A>Советую перейти на ренедринг OpenGL. A>OpenGL порой несколько медленее, но у OpenGL есть ряд серьёзных преимуществ для "не игр". Во-первых, OpenGL не надо распространять, она всегда есть. У меня программа на DirectX9 отказывалась запускатся на голой Windows 2000 SP4 (что вобщем-то нормально).
Если нужна только "прокрутка и масштабирование", то можно использовать DDraw, причём хоть 1-ю версию, которая есть в составе любой Windows (последняя, 7-я, от неё отличается не сильно).
Если нужны спецэффекты и соотвественно D3D/OGL — тогда да, согласен, OpenGL в плане распространения удобнее. Рекомендовать использовать старые версии D3D я буду разве что человеку, имеющему соотвествующий опыт/наработки, или же врагу, чтоб помучился
A>OpenGL не навязывает способ хранения данных, не принуждая к созданию разного рода буферов вершин.
D3D не принуждает создавать буферы — см. DrawPrimitiveUP.
Буферы нужны при наличии большого кол-ва полигонов (>1000) и видеокарты с HWTnL, чтобы эта видеокарта смогла перемолоть их с максимальной эффективностью (буферы могут храниться в видеопамяти -> не надо на каждом кадре гонять геометрию через AGP). В OpenGL есть аналог в виде расширения (VBO).
Re[3]: [GDI] Узкое место - StretchBlt. Возможна ли альтернат
AS>>О как. А про то, что DDB вполне себе могут жить в видеопамяти, вы подумали? Интерфейс DDI\gdi вполне позволяет такие вещи, более того, он на них и ориентирован. Например, на моей машине блиттинг ddb-ddb (или ddb-ScreenDC) занимает в разы меньше времени, чем оный же для ddb-dib. При этом вызовы gdi вполне себе буферизируются, поэтому суммарная производительность вполне и вполне, опять же, при учете нормальных драйверов.
S>Про DDB знаю. Но от применения отпугивало вот это самое "могут жить" (в DirectDraw, если указал в видео — 99% будет в видео); отсуствие каких-либо эффектов, даже примитивного цветового ключа; и ещё некоторые странные побочные эффекты вроде "остановки времени", т.е. замеряемое QueryPerformanceCounter время блиттинга стремится к 0, хотя при большом количестве циклов невооружённым глазом видно, что оно явно не нулевое. Причём не только я с этим сталкивался. Не знаете, как это можно объяснить (не принципом же относительности Эйнштейна ?
Знаю. Это можно объяснить конвейером операций gdi. см. GdiFlash — batch mode.
Более того, это видет к другим интересным эффектам — асинхронности выполнения операций, например, вы можете делать blt DDB и DIB параллельно, что снижается затраты на блиттинг DDB до 0. Протестировать это можно, делая bitblt с диб секции на экран и делая сначала biblt с dib секции в ddb, а затем уже на экран. Получается, что блиттинг из DDB на экран — бесплатен в плане общей производительности.
А>>>В варианте видео->видео DirectDraw, по моим тестам, быстрее GDI в десятки-сотни раз. Stretch на весь экран занимает, как правило, меньше миллисекунды даже на старых картах. К тому же он делается с фильтрацией независимо от версии Windows (StretchBlt может фильтровать только в NT). AS>>Ок, возможно. По крайней мере, результаты для bitblt и stretchblt у меня для gdi отличались в разы. Приведете тесты?
S>Тест (exe): http://slil.ru/23397272
1. То, что GDI в масштабировании провалилась — ну, в общем, согласен. Но это однозначно проблемы драйверов, повторюсь, все интерфейсы для аппаратной реализации масштабирования в DDI есть.
2. Результаты DD blt и stretch — нереальны. У меня 6600 GT c видео на 1200 (GDDR3). Итого при 128 битном доступе это дает максимум 20 мб\с. При честном переносе из одной области памяти в другую получаем примерно 8-10 мб\с, что соответствует полученным мной для gdi результатам DDB. Каким образом у вас получается 600 гб\с? Причем как в блиттинге, так и в стретче?
S>Могу и исходники выложить (Delphi), но ничего сложного там нет — создаётся первичная поверхность, клиппер, поверхность с картинкой (в качестве картинки — снимок рабочего стола). Картинке делается Blt на экран безо всяких задних буферов.
Но резульаты для DDraw нереальны.
AS>> Все зависит от реализации. DDI предоставляет разработчикам полные возможности по аппаратному ускорению стретча в gdi. Я встречал реализации, где блиттинг в ddraw вообще не ускорялся, судя по ощущениям. (i740, такой обрезок, если помните)
S>i740 — это скорее "первый блин комом" Так что кривость драйверов неудивительна. S>И даже если DirectDraw не ускоряется — то во всяком случае он не медленнее GDI/DDB, так?
Не так. Может быть по-всякому — зависит от фантазии разработчика.
A вот наоборот — легко, например, DDB на Radeon 9000 + Win98 тормозит сильнее DIB.
А вот это уже пример лени разработчиков драйвера.
S>Впрочем, здесь я сам начинаю увлекаться седой стариной. Лучше было бы подумать о Висте, применительно к которой это обсуждение вообще будет бессмысленным, по причине реализации GDI через D3D.
??? Насколько я помню, они там переработали модель DDI, и вместо DirectХ теперь WGF, а директх9 и ниже (а также модель драверов DDI) эмулируется.
Здравствуйте, Andrew S, Вы писали:
S>>Про DDB знаю. Но от применения отпугивало вот это самое "могут жить" (в DirectDraw, если указал в видео — 99% будет в видео); и ещё некоторые странные побочные эффекты вроде "остановки времени", т.е. замеряемое QueryPerformanceCounter время блиттинга стремится к 0, хотя при большом количестве циклов невооружённым глазом видно, что оно явно не нулевое. Причём не только я с этим сталкивался. Не знаете, как это можно объяснить (не принципом же относительности Эйнштейна ?
AS>Знаю. Это можно объяснить конвейером операций gdi. см. GdiFlash — batch mode.
Теоретически — да, похоже на правду, многочисленные вызовы BitBlt откладываются в буфер, но не выполняются, замеряемое время очень мало. Потом Windows решает наконец их выполнить, получаем заметные визуально, но необнаруживаемые бенчмарком тормоза.
Практически — GdiGetBatchLimit у меня возвращает 20, т.е. 1000 вызовов BitBlt закэшироваться никак не могут. К тому же GdiSetBatchLimit(1) и GdiFlush после каждого BitBlt на ситуацию никак не влияют.
Хотя может быть, у драйвера своя очередь команд, независимая от GDI'шной.
AS>2. Результаты DD blt и stretch — нереальны. У меня 6600 GT c видео на 1200 (GDDR3). Итого при 128 битном доступе это дает максимум 20 мб\с. При честном переносе из одной области памяти в другую получаем примерно 8-10 мб\с, что соответствует полученным мной для gdi результатам DDB. Каким образом у вас получается 600 гб\с? Причем как в блиттинге, так и в стретче?
В точности те же симптомы, что и у меня с GDI/DDB.
Впрочем, здесь дело может быть не (или не только) в буферизации. При вызове Surface.Blt я не указал DDBLT_WAIT, хотя, наверное, надо было — возможно, без этого флага на большую часть вызовов драйвер возвращает DDERR_WASSTILLDRAWING и ничего не делает.
C Radeon 9000 и интегрированной i915 такого эффекта нет, то ли они асинхронность не поддерживают, то ли у драйвера DDBLT_WAIT зашито по умолчанию. Пробовал задать принудительно DDBLT_DONOTWAIT и DDBLT_ASYNC — всё равно меряется правильно.
Новая версия с DDBLT_WAIT и возможностью тестировать режимы по отдельности, чтобы удобнее было засекать время по часам (мне с GDI/DDB так и пришлось делать — получилась примерно та же скорость, что и DDraw без stretch): http://slil.ru/23409314
S>>Лучше было бы подумать о Висте, применительно к которой это обсуждение вообще будет бессмысленным, по причине реализации GDI через D3D. AS>??? Насколько я помню, они там переработали модель DDI, и вместо DirectХ теперь WGF, а директх9 и ниже (а также модель драверов DDI) эмулируется.
Насчёт внутренних деталей я не в курсе, смысл в том, что StretchBlt должны наконец ускорить до подобающего уровня.
Re[16]: [GDI] Узкое место - StretchBlt. Возможна ли альтерна
AS>>Знаю. Это можно объяснить конвейером операций gdi. см. GdiFlash — batch mode.
S>Теоретически — да, похоже на правду, многочисленные вызовы BitBlt откладываются в буфер, но не выполняются, замеряемое время очень мало. Потом Windows решает наконец их выполнить, получаем заметные визуально, но необнаруживаемые бенчмарком тормоза.
Никаких визуально заметных тормозов. Как только достигается батч лимит, все работает линейно (с условием, конечно, что аппаратно ускоряемые операции не перемежаются с обычными). В моих тестах это вполне видно. Просто надо _правильно_ тестировать — не по _количеству_ выполнений, а выделять промежуток времени, считать количество вызовов и потраченное на них время. И не смешивать различные операции во время тестирования.
S>Практически — GdiGetBatchLimit у меня возвращает 20, т.е. 1000 вызовов BitBlt закэшироваться никак не могут. К тому же GdiSetBatchLimit(1) и GdiFlush после каждого BitBlt на ситуацию никак не влияют. S>Хотя может быть, у драйвера своя очередь команд, независимая от GDI'шной.
Вообще, это довольно непросто в текущем варианте DDI. Да, там есть возможность "отложить" обработку поверхности — но как и делает ли это хоть кто-нибудь — не знаю.
AS>>2. Результаты DD blt и stretch — нереальны. У меня 6600 GT c видео на 1200 (GDDR3). Итого при 128 битном доступе это дает максимум 20 мб\с. При честном переносе из одной области памяти в другую получаем примерно 8-10 мб\с, что соответствует полученным мной для gdi результатам DDB. Каким образом у вас получается 600 гб\с? Причем как в блиттинге, так и в стретче?
S>В точности те же симптомы, что и у меня с GDI/DDB.
Нет, мне думается, что не те же.
S>Впрочем, здесь дело может быть не (или не только) в буферизации. При вызове Surface.Blt я не указал DDBLT_WAIT, хотя, наверное, надо было — возможно, без этого флага на большую часть вызовов драйвер возвращает DDERR_WASSTILLDRAWING и ничего не делает.
Похоже на то.
S>C Radeon 9000 и интегрированной i915 такого эффекта нет, то ли они асинхронность не поддерживают, то ли у драйвера DDBLT_WAIT зашито по умолчанию. Пробовал задать принудительно DDBLT_DONOTWAIT и DDBLT_ASYNC — всё равно меряется правильно.
Может. Завтра посмотрю новый вариант на 6600 GT.
S>C Radeon 9000 и интегрированной i915 такого эффекта нет, то ли они асинхронность не поддерживают, то ли у драйвера DDBLT_WAIT зашито по умолчанию. Пробовал задать принудительно DDBLT_DONOTWAIT и DDBLT_ASYNC — всё равно меряется правильно. S>Новая версия с DDBLT_WAIT и возможностью тестировать режимы по отдельности, чтобы удобнее было засекать время по часам (мне с GDI/DDB так и пришлось делать — получилась примерно та же скорость, что и DDraw без stretch): S>http://slil.ru/23409314
Потестировал. Результаты примерно те же. В общем, что то не так вы делаете, явно. Получаемые для DD результаты анреал, как вы понимаете.
К тому же получаемые у вас результаты для DDB ниже, чем у меня. И меняеются довольно странно между запусками — от 3 до 6 гб\с, даже при большом числе итераций. У меня результаты стабильны, с точностью до кб\с.
Здравствуйте, Andrew S, Вы писали:
AS>Потестировал. Результаты примерно те же. В общем, что то не так вы делаете, явно. Получаемые для DD результаты анреал, как вы понимаете.
Cделал по принципу "крутимся в цикле до тех пор, пока общее время не превысит определённой константы".
На GDI/DDB теперь выдаёт похожие на правду результаты (практически равные DDraw), но вместо положенных 2 секунд крутится в цикле 15 (точнее, вместо любого интервала от 0.2 до 2 секунд получается 15).
Лог временных интервалов при этом имеет вид (в микросекундах):
Очень похоже на буферизацию. Сначала идёт добавление в буфер (очень быстро, 5-6 мкс; параллельно, возможно, выполнение), потом, когда место в буфере заканчивается, драйвер вынужден 15 секунд выполнять всё что туда набилось. Всего итераций получается 16386; размер буфера, видимо, 16384. Или больше, если оно параллельно выполняется.
Если предположить, что у вас на GeForce/DDraw то же самое (у вас есть другие идеи?), то единственный способ получить правильные результаты — забить буфер полностью, чтобы драйвер перешёл на синхронное исполнение команд. Но какой у GeForce размер буфера — неизвестно; может быть, он умеет параллельно выполнять команды с достаточной скоростью и его нужно забивать очень долго. Может быть, проявятся ещё какие-то эффекты, о которых я не имею представления.
В общем, новую версию я могу выложить, но гарантировать правильное измерение...
AS>К тому же получаемые у вас результаты для DDB ниже, чем у меня. И меняеются довольно странно между запусками — от 3 до 6 гб\с, даже при большом числе итераций. У меня результаты стабильны, с точностью до кб\с.
Такие колебания могут быть из-за использования QueryPerformanceCounter, если у вас соответствующий CPU:
AS>>Потестировал. Результаты примерно те же. В общем, что то не так вы делаете, явно. Получаемые для DD результаты анреал, как вы понимаете.
S>Cделал по принципу "крутимся в цикле до тех пор, пока общее время не превысит определённой константы". S>На GDI/DDB теперь выдаёт похожие на правду результаты (практически равные DDraw), но вместо положенных 2 секунд крутится в цикле 15 (точнее, вместо любого интервала от 0.2 до 2 секунд получается 15).
На мой взгляд, что-то вы не так считаете. В моем сампле все точно, работает ровно столько, сколько заказывали. Как будет время, надеюсь, до выходных — выкушу нужные части и выложу. Просто уже самому интересно
Выложил тест на фтп. Сравнивает производительность блиттера для DIB секции и DDB. На каждый тест — по секунду, и цикл наново. Итого — результаты раз в 2 секунды, клавиатуру опрашивается аналогично — раз в 2 секунды. Никаких задержек не наблюдается.
Доступные параметры: -w:width -h:height. Например, -w:64 -h:64.
Без параметров гадит непосредственно на весь экран, так что удобнее перенаправлять вывод в файл (тест консольный).
AS>>>Потестировал. Результаты примерно те же. В общем, что то не так вы делаете, явно. Получаемые для DD результаты анреал, как вы понимаете.
S>>Cделал по принципу "крутимся в цикле до тех пор, пока общее время не превысит определённой константы". S>>На GDI/DDB теперь выдаёт похожие на правду результаты (практически равные DDraw), но вместо положенных 2 секунд крутится в цикле 15 (точнее, вместо любого интервала от 0.2 до 2 секунд получается 15).
AS>На мой взгляд, что-то вы не так считаете. В моем сампле все точно, работает ровно столько, сколько заказывали. Как будет время, надеюсь, до выходных — выкушу нужные части и выложу. Просто уже самому интересно
Здравствуйте, Andrew S, Вы писали:
AS>Выложил тест на фтп. Сравнивает производительность блиттера для DIB секции и DDB. На каждый тест — по секунду, и цикл наново. Итого — результаты раз в 2 секунды, клавиатуру опрашивается аналогично — раз в 2 секунды. Никаких задержек не наблюдается.
AS>http://gzip.rsdn.ru/File/8583/BltTest.zip
AS>Доступные параметры: -w:width -h:height. Например, -w:64 -h:64. AS>Без параметров гадит непосредственно на весь экран, так что удобнее перенаправлять вывод в файл (тест консольный).
Запускаю на Radeon'е, тут же жму Esc. Жду 15 секунд
С размером битмапа 64 * 64 задержки нет — просто потому, что блит такого битмапа делается 5-6 мкс, и карта успевает выполнять команды синхронно.
Собственно результаты:
Src dib: 1024 x 768 x 32
Dst dib: 1024 x 768 x 32
driver loaded
bitmap created: 6a050681
Ok0
768, 1024, 32, 3072Ok // кстати, почему сначала 768, потом 1024? ничего не путаете?
Ok1
Output (32->32): GDI\DIB — 71.93 FPS, 226274962.14 BPS
GDI\DDB — 1166.87 FPS, 3670651626.92 BPS
Похоже на правду, но скорость DDB в 1.3 раза больше чем в моём тесте. На i915 — аж в 2.2 раза.
То ли DDB у вас "более DD", то ли меряете очень хитро (сначала грешил на то, что битмап у меня при выводе обрезается, и, может, это как-то неэффективно делается, да и выводится в окно, а не на экран. Сделал чтобы не обрезался и на экран — всё то же самое).
Ещё тестировал GeForce2MX400. Похоже, там для DDraw есть аналогичный радеоновскому буфер, но работает он несколько более сложным образом:
DDB там не ускорялся, т.к. Win98. А в вашем тесте ещё и глючил, при запуске на полный экран — подвисание, если не на полный — выдаёт нечто совсем уж странное:
Src dib: 128 x 128 x 32
Dst dib: 128 x 128 x 32
driver loaded
bitmap created: f12 // странный handle, битмап не создался, что ли?
Ok0
128, 128, 32, 512Ok
Ok1
8 Гб/c на 150 Мгц SDR — это нечто Ладно, спишем на устаревшую и кривую ОС.
Кстати, по поводу гигабайтов в секунду. Мне кажется, результаты нужно умножать на 2, т.к. выполняется 2 операции, чтение и запись. Или видеокарты умеют их как-то распараллеливать?
Если умножать — тогда врёт и моя программа, намерившая 1.4 Гб/c при макс. теоретической 2.4 Гб/c.