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

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

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

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

Сейчас же у меня рендер работает по такому принципу:
1. Поток рендера (главный поток) отправляет сообщение потоку игровой логики чтобы он начал просчет следующего кадра.
2. Рендер начинает отрисовку кадра, а если текущий кадр не готов, то рисует то что сейчас имеет.
3. Игровая логика как просчитает кадр отправляет рендеру уведомление что кадр готов и засыпает.
4. п.1.

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

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

ПС. У рендера и игровой логики данные о геометрии пока общие.


#1
1:56, 15 мар. 2019

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

#2
(Правка: 2:04) 2:01, 15 мар. 2019

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

#3
5:18, 15 мар. 2019

Misanthrope
> когда многопоточность ради многопоточности начинают приделывать.
Только вот когда оно вдруг понадобится - уже поздно что-то добавлять.

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

zombihello
> ибо кол-во FPS и время кадра такой же как и без многопотока.
оно так не меряется - потоки работают не просто параллельно, а еще и с разной скоростью (если не тормозить) фпс и даже время кадра всегда будет от одного потока. Можно замерить время в каждом потоке - но и это мало что даст

#4
5:43, 15 мар. 2019

что, опять? .__.

#5
8:19, 15 мар. 2019

zombihello

кури UE4

#6
9:45, 15 мар. 2019

innuendo
> кури UE4
там не прокурить))))

#7
(Правка: 9:49) 9:48, 15 мар. 2019

Ты разнёс операции в два потока, но они остались последовательными. Конечно не будет ускорения.

Если ничего за последние лет 10 не поменялось, то один из "кошерных" способов реализации этой фичи заключается в том, что логика и графоний оперируют независимыми моделями мира и как раз логика шлёт команды графонию на изменение его модели (типо "передвинуть модель юнита в точку х, у за время Т с такой-то анимацией"). Причём логика работает с фиксированным шагом, а графоний рисует кадры без задержек (опираясь на время между ними).

#8
9:57, 15 мар. 2019

Tiendil
самый большой вопрос - как это сплоектировать? чтобы оно друг друга постоянно не блокировало... Так как независимы они ровно до тех пор, пока модельку подвинутую физ движком не нужно нарисовать на монитор. А как нуждно - локи потоков на локах через локи

Самым тяжелым будет рендер. а соответственно даже если логика будет в другом потоке - она все равно упрется в скорость рендера - если рендер не успевает рисовать, то другому потоку придется ждать - отсюда и теряется буст многопоточности... Короче вот это вот все как-то хочется понять (тоже вот пытаюсь осилить).
Так-то зафигачить пару потоков не проблема

#9
10:31, 15 мар. 2019

>чтобы оно друг друга постоянно не блокировало
Так не должно, графоний не должен знать о логике ничего. У него должны быть все необходимые для отображения параметры (координаты, направление взгляда, etc).

>если рендер не успевает рисовать, то другому потоку придется ждать
Нет. Не логика должна ждать рендер, а рендер должен гнаться за логикой. То есть, если логика сказала сдвинуть юнит на 5 метров за 1 секунду, то рендер, в зависимости от скорости, может:

- отрисовать один кадр за секудну, нарисовав юнит сразу в конечном месте
- отрисовать два кадра за секунду, свдинув юнит сначала на 2.5 метра, потом ещё на 2.5 метра
- отрисовать 10 кадров за секунду, сдвигая юнит на 0.5 метра.
- отрисовать 100 кадров за секунду, сдвигая на 0.05 метра.

#10
11:07, 15 мар. 2019

Такое разделение ошибочно. Нужно менять как данные представлены в игре, определять зависимости между данными и обрабатывать параллельно данные не имеющие связей. Абсолютно необходимо использование ECS и/или DOD. Так же можно распараллелить генерацию командных буферов для разных задач - один поток делает главный проход, второй тени, потом в главном потоке буферы отправляются в рендер.

#11
11:30, 15 мар. 2019

Tiendil
> Так не должно, графоний не должен знать о логике ничего. У него должны быть все

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


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

#12
11:44, 15 мар. 2019

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

>рендер тяжелее логики
Это смотря какая логика и какой рендер.

> он должен ждать логику
Он не ждёт логику. Он рисует модель мира, которая сейчас у него есть. Логика только даёт команды на изменение модели. Нет команд, рисует idle анимации и т.п.

Логика в таком случае находится на "один шаг логики" в будущем. Для многих игр это допустимо.

#13
11:58, 15 мар. 2019

Ты либо получишь много проблем с мутехами. Либо замотаешься прикручивать локфри. У тебя какие-то ппц-проблемы и ты их можешь решить только потоками? Может ты просто не правильно используешь GAPI?

#14
(Правка: 12:42) 12:14, 15 мар. 2019

war_zes
> самый большой вопрос - как это сплоектировать? чтобы оно друг друга постоянно
> не блокировало... Так как независимы они ровно до тех пор, пока модельку
> подвинутую физ движком не нужно нарисовать на монитор. А как нуждно - локи
> потоков на локах через локи

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

Из недостатков - вводится инпут-лаг, становящийся более заметным с увеличением разбиения на кадры этого "конвеера". То есть нажаитие  клавы/геймпада мы прочли два кадра назад, а результат нарисовали только сейчас. Когда машина шустрая и выдает стопицот фпс - это будет не заметно. Заметно это станет при дропах FPS.

Шаблон "Конвеер" называется.

Для совсем разделения, можно применить следующий способ - то же двойная буфферизация, при этом логика с физоном работают независимо по своему таймеру. От самого физона/логики отделяется простая для вычислений часть вроде кинематики с вектором скорости/ускорения, которая передается грофонию. Пока физон не просчитал следующий кадр, грофон несколько кадров интерполирует вычисления  путем расчета координатобъекта/скелета анимации по Sn=Sn-1+V*t+at^2/2, при переключении буферов вдобавок старается сделать красиво, интерполируя то что насчитал физон с тем что натворил он сам.

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