tgoop.com/unsafecsharp/208
Last Update:
Есть CPU, есть GPU.
GPU - это графический ускоритель, т.е. дополнительное устройство для ускорения определенных операций, а именно - рендеринга.
Между ними существует промежуточный буфер. Буфер команд, очередь если точнее.
CPU наполняет этот буфер. а GPU забирает из него и удаляет команду, которую забрал.
Если CPU заполняет буфер быстрее, чем GPU потребляет, то рано или поздно он упрется в максимальный размер буфера. В таком случае мы говорим, что у нас GPU bound, т.к. центральный процессор простаивает по вине GPU.
И наоборот - если GPU слишком быстро потребляет команды, а CPU не успевает наполнять буфер - то простаивает GPU и у нас CPU bound.
(это, разумеется, не все причины почему у нас может возникнуть баунд).
Любое сообщение CPU и GPU - это команда.
В понимании графического ускорителя не существует такого понятия как drawcall и setpass call. Об этом ниже.
Есть "состояние пайплайна" - "state" и команды отрисовки (нарисуй просто, нарисуй с буфером индексов, нарисуй индирект, нарисуй инстансингом, итд).
(Причём на разных графических API есть разная "детализация" этого состояния).
Итай, стейт - это обобщение для: шейдерные программы для разных этапов конвейера (вертексный, фрагментный, итд), значения всяких ресурсов, значения хардварных переключателей, и пр.
В старых API - DX11 и OpenGL / GL ES - стейт один на весь GPU. В новых - можно их на CPU собирать, кэшировать и экономить на сборке.
Допустим, говорим про GL.
Там ты стейт собираешь как колоду карт, по очереди, отдельными командами, каждый кадр заново:
- Вот текстурка в этот слот.
- Вот буфер в этот слот.
- Вот шейдерная программа для вертексов
...
- Вызов команды отрисовки.
Можно воспринимать этот вызов отрисовки как нажатие кнопки на блендере. Нажал - и всё применилось.
При этом разные команды для изменения состояния GPU - имеют разную "стоимость".
Стоимость эта применяется дважды - сначала CPU надо её выполнить - т.е. подготовить для неё данные, провалидировать и поместить команду и данные в буфер.
Затем, при считывании, драйвер GPU должен взять эту команду и применить её в свой стейт.
Дроуколл - это термин программистов, обобщение, для вызова отрисовки + набор команд на изменение стейта, которые надо доприменять после прошлого дроуколла.
- | тут-старый-дроуколл |
-блабла
-блаблабла
-отрисовка.
Вот эти три команды - дроуколл.
Чтобы минимизировать оверхед на вот эти мотыляния стейта туда-сюда, программисты пытаются "батчить" команды. Ведь после вызова команды отрисовки, драйвер не сбрасывает стейт. И если есть команды, которые можно выполнить с одним и тем же стейтом - мы можем здорово сэкономить.
Такая пачка команд называется "батч".
А самый первый и самый длинный, долгий, тяжелый дроуколл, когда у нас выставляется весь стейт - это SetPass Call.
"Идеальный" батч можно посмотреть рендердоком на партикл системе (которая шурикен). Там один сетпассколл и много дроуколлов из одной команды отрисовки.
Обычно у нас таких идеальных батчей больше нет нигде :))
Даже в том же SRP батчере у нас в дроуколл'е приходится мапить небольшие участки буферов, вертексные-индексные буферы, текстуры.
Но это всё равно изрядно дешевле, чем каждый drawcall выстраивать стейт с нуля.
p.s. и на десерт :)
Современные драйверы умеют анализировать загрузку GPU и могут выполнять несколько разных дроуколлов одновременно. Важный фактор - чтобы они не зависели друг от друга. Так, к примеру, GPU может считать вертексный шейдер одного меша в одном дк и фрагментный другого в другом.
Автор: @shiko_q
Источник: https://www.tgoop.com/unity_cg/52328
#cpu #gpu #rendering
BY Unity: Всё, что вы не знали о разработке
Share with your friend now:
tgoop.com/unsafecsharp/208