Использование многопоточности между игровым циклом и openGL

Говоря в контексте игры, основанной на рендерере openGL:

Предположим, что есть два потока:

  1. Обновляет логику игры и физику и т. д. для игровых объектов

  2. Делает вызовы drawGL для каждого игрового объекта на основе данных в игровых объектах (этот поток 1 продолжает обновляться)

Если у вас нет двух копий каждого игрового объекта в текущем состоянии игры, вам придется приостановить Thread 1, в то время как Thread 2 сделает обратные призывы, иначе игровые объекты будут обновляться в середине призывного вызова для этого объект, что нежелательно!

Но прекращение потока 1, чтобы безопасно сделать призывы рисования из потока 2, уничтожает всю цель многопоточности /параллелизма

Есть ли лучший подход для этого, кроме использования сотен или тысяч или объектов или ограждений синхронизации, чтобы использовать многоядерную архитектуру для производительности?

Я знаю, что все еще могу использовать многопоточность для загрузки текстур и компиляции шейдеров для объектов, которые еще не являются частью текущего состояния игры, но как это сделать для активных /видимых объектов, не вызывая конфликта с рисованием и обновлением

Что делать, если я использую отдельную блокировку синхронизации в каждом из игровых объектов? Таким образом, любой поток будет блокировать только один объект (идеальный случай), а не весь цикл обновления /рисования! Но как дорого стоит фиксация на каждом объекте (игра может иметь тысячу объектов)?

10 голосов | спросил Allahjane 5 Jpm1000000pmMon, 05 Jan 2015 19:01:01 +030015 2015, 19:01:01

1 ответ


12

Описанный вами подход с использованием блокировок будет очень неэффективным и, скорее всего, медленнее, чем использование одного потока. Другой подход к хранению копий данных в каждом потоке, вероятно, будет хорошо работать «по скорости», но с чрезмерной стоимостью памяти и сложностью кода, чтобы синхронизировать копии.

Существует несколько альтернативных подходов к этому, одно популярное решение для многопоточного рендеринга - использование двойного буфера команд. Это состоит в том, что выполняется работа с внутренним коннектором рендеринга в отдельном потоке, где выполняются все вызовы вызова и связь с API-интерфейсом рендеринга. Линейный поток, который запускает логику игры, обменивается данными с внутренним рендерером с помощью буфера команд (с двойной буферизацией) . При этой настройке у вас есть только одна точка синхронизации при завершении кадра. В то время как front-end заполняет один буфер с помощью команд рендеринга, внутренний сервер потребляет другой. Если оба потока хорошо сбалансированы, никто не должен голодать. Однако этот подход является субоптимальным, поскольку он вводит задержку в обработанных кадрах, плюс, вероятно, OpenGL-драйвер уже будет делать это в своем собственном процессе, поэтому необходимо будет тщательно оценить прирост производительности. В лучшем случае он использует только два ядра. Этот подход использовался в нескольких успешных играх, например, Doom 3 и Quake 3

Более масштабируемые подходы, которые лучше используют многоядерные ЦП, основаны на Основы Threading для игр от Intel.

  • Эффективный параллелизм Herb Sutter (несколько ссылок на другие полезные ресурсы на этой странице).

  • ответил glampert 5 Jpm1000000pmMon, 05 Jan 2015 20:41:42 +030015 2015, 20:41:42

    Похожие вопросы

    Популярные теги

    security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132