Войти
ПрограммированиеФорумОбщее

Многопоточность в игровом движке (2 стр)

Страницы: 1 2 3 4 5 Следующая »
#15
12:45, 15 мар. 2019

Tiendil
> У графония свой объект с координатами и данными графики. Логика шлёт графонию
> команду "меняй координаты своего объекта в такие с такой-то скоростью" графоний
> и меняет по кадрам с учётом скорости рендера.

И в результате игрок на экране будет видеть совсем не то что происходит в логике - потому что графоний еще рисует старые координаты, а логика уже давно подсчитала новые

Короче, вот скоростной шутер, игрок нажал кнопку, логика все обработала, но рендер загнулся на рендере тяжелого шейдера и еще не успел обработать то что прислала логика - игрок видит старый кадр и его уже убили. Хреновый это подход.


#16
(Правка: 13:28) 13:20, 15 мар. 2019
И в результате игрок на экране будет видеть совсем не то что происходит в логике - потому что графоний еще рисует старые координаты, а логика уже давно подсчитала новые

Это норм.

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

Это так во всем мире и работает. Аналогичная херня с сетевым лагом и лаг предикшоном. Решается разработчиками путем "пусть эти нищеброды покупают себе новые пеки и проводят нормальный интернет".

В случае конвеерного подхода - весь конвеер затыкается на этапе когда логика отработала и готова свапнуть буфер, а рендер еще рисует, при этом скорость обработки логики падает до скорости рендера и описанной тобой проблемы не возникает - логика всегда на 1 кадр впереди отображения, если логика готова а кадр не готов, все затыкается и начинает напоминать юзеру о походе в компьютерный магазин.

Или левел-дизайнерам на консолях намекает "урезать осетра и прочие хотелки"

Хреновый это подход.

Используется всеми именитыми инхауз движками вроде фростбайта, о чем сами разработчики регулярно рассказывают на GDC.

#17
14:51, 15 мар. 2019

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

Если думаете, что под юникс-системами лучше, то нет, они по умолчанию переключают потоки еще реже. Их можно переконфигурировать, но не ожидаете же вы, что каждый игрок будет перекомпилировать ядро луникса чтобы поиграть... С приоритетами потоков там бардака поменьше, чем в винде, разве что.

#18
8:47, 20 мар. 2019

zombihello, как мне кажется - распараллеливание логики и рендера имеет смысл только в том случае, если логика работает медленнее рендера или рендер и логика должны выполняться на разных машинах (те же онлайн игры).

#19
9:11, 20 мар. 2019

lookid
> Ты либо получишь много проблем с мутехами. Либо замотаешься прикручивать
> локфри. У тебя какие-то ппц-проблемы и ты их можешь решить только потоками?
Не обязательно. Есть два варианта:
1) Представь, что у Entity есть несколько компонент, например Visual, Audial, Physics. Каждая подсистема работает не с Entity, а только со своим вариантом компонент, т.е. физика обновляет Physics-модель, рендер рисует визуальные модели. Поверх всего это работает какая-то служба синхронизации, которая по определённым правилам перетаскивает данные между компонентами для каждого Entity, ставя блокировку только на обрабатываемый в данный момент объект. Естественно всё это оптимизировано, перенос данных почти мгновенный, блокировки очень кратковременные, обновляем только изменившиеся объекты и т.д.
2) У объекта несколько моделей состояния, физика обновляет одну, рендер рендерит другую, потом модели атомарно флипаются (аналог двойной буферизации).

#20
(Правка: 12:20) 11:50, 20 мар. 2019

Разбиение на потоки имеет смысл по следующей причине: чтобы не поиметь конских инпут лагов - на каждом кадре обязательно принуждать драйвер к синхронизации цпу и гпу. Но в таком случае основной поток львиную долю времени проводит в вызове SwapBuffers (кажется, в директиксе то же называется Present) или в командах, вынуждающих драйвер к синхронизации (например, glReadPixels из специального маленького мипа рендербуфера). Факт в том, что основной поток дохрена времени ждёт всей этой байды - раз в это время момент надо выполнять логику в отдельном логическом потоке. Чтобы когда рендер проснётся - ему уже был подан завтрак в постель.

Синхронизация в такой системе - это не вредно, даже если она занимает 1/3 времени. На потоки разносим, чтобы избавиться от ограничений по времени: логика в основном потоке обязана быть поджарой, обходиться ~10% одного ядра в оптимистичном случае. Иначе сажает fps. Логика в выделенном потоке может быть жирной и жрать хоть целое ядро - на fps это едва скажется.

Угадайте, какая логика получится у новичка? Поджарая или таки жирная?

P.S. Про SwapBuffers - это моё оригинальное исследование. Приделал к своему движку самодельный профайлер и научил кроме fps показывать гистограммы, где цветами размечено какой поток сколько на что тратит. Оченно интересно получилось - потом отдельную тему создам как буду готов всё это показывать.

P.P.S. Вы всё сделали в одном потоке оптимально, всё работает - и тут, !внезапно!, виста, оконный режим, включённый аэро. И вызов SwapBuffers тяжелеет раза в три.
Это я к тому, что дерьмо случается.

#21
12:03, 20 мар. 2019

Cheb
> Но в таком случае основной поток львиную долю времени проводит в вызове SwapBuffers
В вулкане больше всего времени тратится на отправку команд на гпу (vkQueueSubmit) чем на ожидание завершения рисования предыдущего кадара (vkWaitForFences). В этом плане новые апи получше.

#22
12:19, 20 мар. 2019

/A\
> В вулкане больше всего времени тратится на отправку команд на гпу
> (vkQueueSubmit) чем на ожидание завершения рисования предыдущего кадара
> (vkWaitForFences). В этом плане новые апи получше.
Тогда тем более имеет смысл в отдельный поток выделять рендер, если у него ожидания по всему рабочему процессу размазаны.

#23
12:24, 20 мар. 2019

>В этом плане новые апи получше
Охотно верю, но проводили лы вы профайлинг на самом днище (ака минимальные системные требования)?
Именно там всё говно вся суровая правда обычно и вылезает.

#24
12:35, 20 мар. 2019

ну так рендер тоже должен быть многопоточным

#25
13:30, 20 мар. 2019

gamedevfor
> ну так рендер тоже должен быть многопоточным
На дх11 и огл драйвер создает дополнительные потоки, поэтому если ты сделаешь N рендер потоков, то в худшем случае получишь еще N потоков драйвера. Это где-то в презентации дайс было.

#26
13:54, 20 мар. 2019

где можно посмотреть примеры Lock-Free на примере движков?

#27
14:14, 20 мар. 2019

/A\
> В вулкане больше всего времени тратится на отправку команд на гпу
> (vkQueueSubmit) чем на ожидание завершения рисования предыдущего кадара
> (vkWaitForFences)
Это правда только если цпу лимитед? Так то всякие варианты возможны и все в общем случае не так

#28
14:43, 20 мар. 2019

kas
> Это правда только если цпу лимитед?
Если у тебя цпу простаивает, а рендер идет очень долго, то результат будет другой, но у меня в среднем именно такой расклад как я описал.

#29
3:52, 21 мар. 2019

nonamezerox
> Разделить по времени на два или более кадра (в текущем обрабатывается ввод и
> физон, графоний при этом рисует результат предыдущего расчета) и,
> соответсвенно, использовать два буфера - в один пишет физон, из другого
> одновременно читает грофон, по окончанию процесса поменять местами.

Я примерно так у себя сделал. Подсмотрел этот вариант в исходниках doom3. С выключенной вертикальной синхронизацией все работает нормально:
mt1 | Многопоточность в игровом движке
Это запись двух кадров на одной временной шкале. F - вспомогательный поток, B - основной поток с GL командами (ГПУ и ЦПУ таймеры синхронизированы не идеально, но думаю этого достаточно для отладки). С включенной синхронизацией соответственно появляется задержка:
mt2 | Многопоточность в игровом движке
Это можно как-то победить? Если на пк я могу выключить синхронизацию, то на андроиде это сделать невозможно. Я видел упоминание этой проблемы без решения. Неужели дум3 так и работал? Или я где-то ошибся?

Страницы: 1 2 3 4 5 Следующая »
ПрограммированиеФорумОбщее