OpenGL асинхронный рендер сцены, который занимает несколько секунд - PullRequest
0 голосов
/ 04 марта 2019

Я реализовал фрактальный генератор Мандельброта, используя wxWidgets и OpenGL.Вычисление выполняется внутри фрагментного шейдера, и я использую виджет wxGLCanvas для отображения результата.Это работает хорошо, но когда я хочу сделать экспорт в высоком разрешении, поток блокируется на несколько секунд, что останавливает пользовательский интерфейс.

Изначально я попытался переместить весь код рендеринга (и создание контекста) в отдельныйпоток рендеринга, но я обнаружил, что блокируется не только поток рендеринга, но ВСЕ потоки.Это может быть легко продемонстрировано созданием нового потока перед выполнением рендеринга, который просто печатает сообщение на стандартный вывод в цикле.Было бы до печати 1 сообщения перед замораживанием, а затем возобновление после завершения рендеринга.

Чтобы выполнить экспорт файла, я сначала рендеринг в текстуру, а затем считываю пиксели в основную память с glGetTexImage.Визуализация происходит асинхронно, как и следовало ожидать, но функция glGetTexImage будет блокировать (опять же, это ожидается).Поэтому я попытался использовать glFenceSync в сочетании с glGetSynciv для вызова glGetTexImage только после достижения ограждения, указывающего на завершенный рендеринг.

Я мог подтвердить, что вызов отрисовки немедленно возвращался, но в тот момент, когда я вернулся в цикл событий wxWidgetsчтобы дождаться окончания рендеринга, все потоки в приложении остановятся.Я полагаю, что, возможно, wxWidgets выполняет вызов OpenGL, который вызывает синхронизацию (например, что-то в wxGLCanvas) - я вполне уверен, что это не было в моем коде.

Я не уверен, почему все потоки блокировалисьпо вызову glGetTexImage, а не только по потоку рендеринга.Я подумал, что это может быть причудой моей установки (аппаратное обеспечение, драйвер, ОС и т. Д.), Но получил тот же результат на совершенно другой платформе.

Единственный оставшийся вариант, о котором я могу подумать, - это выполнитьэкспорт рендеринга в другом процессе с собственным контекстом OpenGL.Если я все еще буду использовать wxGLCanvas для настройки контекста, мне, вероятно, понадобится видимое окно на экране, что не идеально.Кроме того, если пользователь попытается закрыть окно во время рендеринга, оно не будет отвечать.

Есть идеи?

1 Ответ

0 голосов
/ 06 марта 2019

Не столько решение, сколько обходной путь (предложенный derhass в комментариях) - разделить рендер на несколько меньших рендеров.Я рисую изображение в горизонтальных полосах высотой 10 пикселей и вызываю wxSafeYield () между ними, чтобы пользовательский интерфейс оставался отзывчивым (и пользователь может прервать рендеринг, если он занимает слишком много времени).

Дополнительным преимуществом является меньшая опасность перегрузки графического процессора.Перед выполнением этого я однажды запустил длинный рендеринг, который заставил мои дисплеи отключиться, и мне пришлось сделать полную перезагрузку.

...