LINUX.ORG.RU

OpenGl и потоки

 , ,


1

3

Привет, всем!

Вопрос к программистам C со стажем. Вот рекомендуемая архитектура OpenGL приложения (на базе SDL2):

while(loop)
{
  обработка событий окна();
  отрисовка_контента_3D();
  переключение_буфера_окна();
  асинхронный_обмен_данными();
}

Попытался отделить в два разных потока

  • обработчик событий окна (взаимодействие с пользователем),
  • отрисовку 3D-контента (GLSL программа, пересчет матрицы вида ... и переключение графичеких буферов окна).

Пробовал запускать каждый из пунктов одним раздельным потоком, но либо события не обрабатываются, либо GLSL бросает исключение, что окно не активно.

Весь вечер терзал поисковики пытаясь понять что не так. В итоге пришел к выводу, что такой фокус невозможен. По крайней мере на SDL2. Мануал по библиотеке SFML на это даже явно указывает.

Собственно вопрос: кто серьезно занимался OpenGL приложениями, я ничего не перепутал? Может кто-то встречал решение, или библиотеку которая может запустить раздельными потоками обработчик событий и вывод контента?


Отрисовка и общение с пользователем - всегда один и тот же поток. Так в десктопных ГУИ, так на андроиде, так в браузере, так в OpenGL.

Про асинхронный обмен на первом этапе забудь. Пока работает без него - радуйся жизни.

anonymous
()

В теории можно (ну, почти - "...Again, it doesn't improve performance."):

https://www.opengl.org/wiki/OpenGL_and_multithreading

в форме небольшого трюка - контекстов создается два и данные между ними расшариваются. В общем, затраченные усилия не дают (пропорционального) увеличения производительности рендеринга. А с единственным контекстом так не получается - архитектура не та.

bigov
() автор топика

Зачем? Обработка пользовательского ввода, как правило, не занимает много времени.

m0rph ★★★★★
()

Контекст OpenGL всегда принадлежит некоторому потоку. Можно забрать его в другой поток, через EGL или другой платформо-зависимый API. Поскольку во всех оконных ОС контекст OpenGL привязан ещё и к окну, то разделить обработку событий и рисование начисто вряд ли получится.

Но есть более хитрые способы: например, работу с API ОС и OpenGL вести в одном потоке, а логику программы прогонять в другом. Получается, что поток рендеринга будет просто брать события ОС и кидать их в свою потокобезопасную очередь, а также принимать объекты-команды рисования, такие как «нарисуй mesh», «нарисуй спрайт», «используй такой-то материал (текстуру, цвет, шейдер)».

Если объекты-команды рисования будут на хорошем и удобном для обоих потоков уровне абстракции, то

  • поток рендеринга будет только складывать события в очередь и рисовать по командам рисования (возможно, сортируя их по одинаковым материалам для сокращения числа batches)
  • поток логики будет только диспатчить события из очереди, диспатчить свои внутренние события типа «выполнить метод через 1 секунду после того как положили в очередь», и отправлять команды потоку рендеринга.

Чем меньше блокировок и чем лучше команды подходят для сортировки для уменьшения числа переключений состояния, тем выше производительность.

quiet_readonly ★★★★
()
Последнее исправление: quiet_readonly (всего исправлений: 1)
Ответ на: комментарий от quiet_readonly

не согласен только с термином «более хитрые». Тут больше подходит «хорошие». Думаю, описанная Вами архитектура приложения наиболее оптимальная.

В дополнение, еще не стоит забвать про PBO: Pixel Buffer Object

bigov
() автор топика
Ответ на: комментарий от anonymous

Отрисовка и общение с пользователем - всегда один и тот же поток. Так в десктопных ГУИ, так на андроиде, так в браузере, так в OpenGL.

Так проще всего. Хотя мсьи могут заморочиться и сделать «не так»... Но нужно четко знать ответ на вопрос зачем, потому что сопутсвующий геморрой трудно оправдать :)

Про асинхронный обмен на первом этапе забудь. Пока работает без него - радуйся жизни.

this, потому что в любой гуйне типа Qt и в SDL все что не в основном потоке — хочет «ручной» прокачки событий :)

slackwarrior ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.