Я пишу приложение для просмотра 3D-моделей в качестве хобби-проекта, а также в качестве тестовой платформы, чтобы опробовать различные методы рендеринга.Я использую SDL для управления окнами и событиями, а OpenGL для 3D-рендеринга.Первая итерация моей программы была однопоточной и работала достаточно хорошо.Тем не менее, я заметил, что однопоточная программа приводила к тому, что система становилась очень вялой / медленной.Мое решение состояло в том, чтобы переместить весь код рендеринга в другой поток, освобождая тем самым основной поток для обработки событий и предотвращая перехват приложения.
Это решение работало с перебоями, программа часто зависала из-за меняющегося (и, на мой взгляд, странного) набора ошибок, исходящих в основном из системы X Window.Это заставило меня усомниться в моем первоначальном предположении, что, пока все мои вызовы OpenGL происходят в потоке, в котором был создан контекст, все должно работать.Проведя большую часть дня в поисках ответа в Интернете, я полностью озадачен.
Более кратко: возможно ли выполнить 3D-рендеринг с использованием OpenGL в потоке, отличном от основного потока?Могу ли я по-прежнему использовать кроссплатформенную библиотеку окон, такую как SDL или GLFW, с этой конфигурацией?Есть ли лучший способ сделать то, что я пытаюсь сделать?
До сих пор я занимался разработкой для Linux (Ubuntu 11.04) с использованием C ++, хотя я также чувствую себя комфортно с Java и Python, если естьрешение, которое работает лучше на этих языках.
ОБНОВЛЕНИЕ: В соответствии с просьбой, некоторые пояснения:
- Когда я говорю «Система становится вялой», я имею в виду взаимодействие срабочий стол (перетаскивание окон, взаимодействие с панелью и т. д.) становится намного медленнее, чем обычно.Перемещение окна моего приложения занимает время порядка секунд, а другие взаимодействия достаточно медленные, чтобы раздражать.
- Что касается вмешательства в оконный менеджер композитинга ... Я использую оболочку GNOME, которая поставляется с Ubuntu11.04 (оставаясь в стороне от Unity на данный момент ...), и я не смог найти никаких вариантов отключения эффектов рабочего стола, как это было в предыдущих выпусках.Я предполагаю, что это означает, что я не использую оконный менеджер композитинга ... хотя я могу быть очень неправ.
- Я полагаю, что "X-ошибки" - это ошибки сервера из-за сообщений об ошибках, которые я получаю в терминале.Более подробная информация ниже.
Ошибки, которые я получаю с многопоточной версией моего приложения:
XIO: фатальная ошибка ввода-вывода 11 (ресурс временно недоступен) на X-сервере ": 0.0"после 73 запросов (обработано 73 известно) с 0 оставшимися событиями.
X Ошибка неудавшегося запроса: BadColor (неверный параметр Colormap) Главный код операции неудавшегося запроса: 79 (X_FreeColormap) Идентификатор ресурса в неудавшемся запросе: 0x4600001 Серийный номернеудавшегося запроса: 72 Текущий серийный номер в выходном потоке: 73
Игра: ../../src/xcb_io.c:140: dequeue_pending_request: Утверждение `req == dpy-> xcb-> pending_requests 'не удалось.Прервано
Я всегда получаю одну из трех ошибок, описанных выше, которые я получаю, меняется, по-видимому, случайно, что (на мой взгляд) может показаться, что моя проблема действительно связана с моим использованиемнитей.Имейте в виду, что я учусь по ходу дела, поэтому есть очень хороший шанс, что в моем невежестве по пути будет что-то довольно глупое.
РЕШЕНИЕ: Для всеху кого возникла похожая проблема, я решил свою проблему, переместив свой вызов на SDL_Init(SDL_INIT_VIDEO)
в поток рендеринга и заблокировав инициализацию контекста с помощью мьютекса.Это гарантирует, что контекст создается в потоке, который будет его использовать, и предотвращает запуск основного цикла до завершения задач инициализации.Упрощенная схема процедуры запуска:
1) Основной поток инициализирует struct
, который будет разделен между двумя потоками и который содержит мьютекс.
2) Основной поток порождает поток рендеринга и спит в течение короткого периода (1-5 мс), что дает время потока рендеринга для блокировки мьютекса. После этой паузы основной поток блокируется при попытке заблокировать мьютекс.
3) Поток рендеринга блокирует мьютекс, инициализирует видеоподсистему SDL и создает контекст OpenGL.
4) Поток рендеринга разблокирует мьютекс и входит в его «цикл рендеринга».
5) Основной поток больше не блокируется, поэтому он блокирует и разблокирует мьютекс перед завершением шага инициализации.
Обязательно прочитайте ответы и комментарии, там много полезной информации.