wglShareList и миф рендера в несколько окон (комментарии)
Это сообщение сгенерировано автоматически.
Полезная подсказка.
У меня не получается рисовать в несколько окон с vsync-ом. Свопаю окна по очереди, фпс падает в соответствии с количеством окон: 1 окно - 60 фпс, 2 окна - 30 фпс, 3 окна - 20 фпс и т.д.
ОС - windows xp. Подскажите, как делать правильно?
SunnyBunny
> Полезная подсказка.
Наоборот.
@!!ex
> Правильный способ рисования в несколько окон...
Правильно не рисовать в несколько окон. И уж тем более не вызывать wglMakeCurrent в каждом кадре, ибо дорого.
eXmire
Правильно не рисовать в несколько окон. И уж тем более не вызывать wglMakeCurrent в каждом кадре, ибо дорого.
Ну иногда нужно. В особенности превьюшки всякие в диалоговых окнах и т.п. Правда я в этом случае создаю отдельный рендерконтекст, и рисую в нем, ибо по факту общих данных минимум (а бывает и вообще нет копирования данных). Но скакать рендер контекстом по окнам я соглашусь, тоже не дело. Хотя технически можно конечно, ну и от задачи зависит. Если в той же превьюшке нужно только на WM_PAINT рисовать, когда ОС требует перерисовки - то можно и скакнуть 1 раз несколько секунд/минут.
MrShoor
> Ну иногда нужно. В особенности превьюшки всякие в диалоговых окнах и т.п.
Об этом да, забыл. В случае диалоговых окон переключение контекста по окнам подойдет, там на производительности это не скажется.
SunnyBunny
У меня не получается рисовать в несколько окон с vsync-ом. Свопаю окна по очереди, фпс падает в соответствии с количеством окон: 1 окно - 60 фпс, 2 окна - 30 фпс, 3 окна - 20 фпс и т.д.
ОС - windows xp. Подскажите, как делать правильно?
В Windows 7 и Linux оно иногда умудряется рисовать с V-Sync из одного потока в несколько окошек без кратного проседания FPS.
Возможно, функция свопа возвращает несколько раньше, нежели новый кадр начинает выводится на монитор.
В Windows XP, по всей видимости, функция swap'a для первого окна возвращается строго после, и следующее окно в очереди ждёт следующего синхрокадра.
Поэтому своп приводит к кратному падению FPS.
Вообще opengl32.dll имеет малодокументированную функцию wglSwapMultipleBuffers, которая позволяет свопать сразу список окошек.
Но увы, эту функцию вендоры не перебивают и всё что она делает - в цикле вызывает обычный своп для каждого окна.
Вендоры имеют собственные реализации подобной штуки через расширения вида WGL_NV_swap_group, но доступны они только для профессиональных карт.
По сути, единственный способ избежать падения FPS, который я вижу - рисовать каждое окно в отдельных потоках (что вызовет дополнительные проблемы, если хочется шарить ресурсы).
eXmire
> Правильно не рисовать в несколько окон.
И как же тогда делать многооконный рендер, если не секрет? :)
gkv311
Можно попробовать в отдельных потоках только Swap делать. А рисовать все как и обычно.
MrShoor
> равда я в этом случае создаю отдельный рендерконтекст
Ну то есть ты не понял что там вообще написано?
Создание отдельных рендер контекстов - это костыль. Который может приводить(и приводит) к проблемам.
Собственно я раньше сам делал многооконный рендер через отдельный контекст на каждое окно. Пока не отловил проблем и не начал копаться. Пока не выяснил, что создание рендер контекстов для отдельных окон - это не правильное использовани контекстов.
eXmire
> И уж тем более не вызывать wglMakeCurrent в каждом кадре, ибо дорого.
Не дороже рендера в отдельные контексты.
@!!ex
что создание рендер контекстов для отдельных окон - это не правильное использовани контекстов.
Я бы не стал так категорично говорить.
Прочитав статью полгода назад, я решил переделать свой рендерер на Windows и Linux под использование одного контекста (на Mac OS X остановился - ибо лень).
За исключением дополнительных заморочек (таких как проставление каждый кадр вьюпорта), никаких существенных отличий в поведении я не заметил.
Проблем никаких не решило, новых, к счастью, не добавилось.
Единственное, что действительно решает проблемы - это использование одного окна вместо нескольких, но это допустимо только в полноэкранном режиме...
@!!ex
> И как же тогда делать многооконный рендер, если не секрет? :)
Не делать.
@!!ex
> Не дороже рендера в отдельные контексты.
Тут дело уже не в дороговизне, а в том, что дерганье OpenGL из разных потоков одновременно — прямая дорога к багам драйвера и внутренним синхронизациям.
gkv311
> Проблем никаких не решило
Повторюсь - текст написан не с бухты барахты. Текст написан на основе реального опыта.
Проблемы решаются. В частности, одна из проблем в тексте написана. Остальные сейчас уже не вспомню.
eXmire
> Тут дело уже не в дороговизне, а в том, что дерганье OpenGL из разных потоков
> одновременно — прямая дорога к багам драйвера и внутренним синхронизациям.
В тексте ни слова про потоки. Речь об отдельных окнах. А не о многопоточности.
eXmire
> Не делать.
Вот реальное приложение на котором, собственно, обкатывался подход:
Как это реализовать без отдельных окон и рендера в них?
@!!ex
Использование wglShareList для задачи рендера в несколько окон в принципе возможно, но может привести к трудноуловимым багам.
Например, wglShareList требует, чтобы все контексты были созданы ДО того, как будут загружены какие-либо данные в видеопамять.
При этом требование не жесткое, и все вполне может работать на одних машинах и не работать на других.
Ладно, соглашусь, встречал проблемы с расшариванием контекстов.
Один из не самых старых выпусков Catalyst стал отказывать шарить контексты для окошек, созданных на разных мониторах.
Пришлось прикручивать workaround - создавать все дополнительные окна там же, где и главное окно, а перед Show двигать его на правильное место.
Хотя с "загружены какие-либо данные в видеопамять" - это какое-то странное утверждение.
Подобные детские проблемы я наблюдал, когда wglShareList для нового контекста звался не в то время (при этом важно, чтобы не создать никаких ресурсов до wglShareList в новом контексте - в старом как раз ресурсы могут уже быть).
http://www.opengl.org/wiki/Platform_specifics:_Windows#wglShareLists
The best time to call wglShareLists is after creating the GL contexts you want to share, but before you create any objects in either of the contexts. If you create objects, then there is a chance that wglShareLists will fail.
Внезапно это не мои фантазии, а вполне себе из доки по OGL.
@!!ex
> Ну то есть ты не понял что там вообще написано?
> Создание отдельных рендер контекстов - это костыль. Который может приводить(и
> приводит) к проблемам.
> Собственно я раньше сам делал многооконный рендер через отдельный контекст на
> каждое окно. Пока не отловил проблем и не начал копаться. Пока не выяснил, что
> создание рендер контекстов для отдельных окон - это не правильное использовани
> контекстов.
Нука нука? Какие проблемы в создании второго контекста и рендера в него?
> Вот реальное приложение на котором, собственно, обкатывался подход:
> Как это реализовать без отдельных окон и рендера в них?
Я рабочий стол делал общим, делал окошко на весь рабочий стол, и рендерил в него. Надо сделать 8 рендеров в одно окно? Юзаем glViewport. На порядок быстрее чем скакать контекстом, и реально огрести проблемы, как тут уже сказали с glSwapBuffers и VSync-ом.
Тема в архиве.