Publish @jimon: Про тайловые рендеры общо

Рассказы про потроха и “как это все работает” часто случаются на ровном месте – кто-то спросил про некую конкретную деталь, а потом кто-то другой спросил “можно про это подробнее?”. Это то, почему беседы вживую такие полезные – возникают случаи рассказать и люди готовы рассказывать.

В этот раз в очередной раз коснулись темы мобильных GPU и то, как они внутри работают. Оно интересно и в смысле краткого экскурса, и в смысле некоторых низкоуровневых деталей (все, например, понимают почему и как именно альфа-тест на i-девайсах тормозит?)


People in this conversation:
Simon Kozlov Add
Engineer at ROBLOX (www.roblox.com), previously at Microsoft. And ClosedCircles was my idea.
Pavel Nakaznenko (Crio) Add
Programmer (Xbox 360, PS3, PC)
at Darkside Games Studio
http://dtf.ru/person/cv.php?id=835
Sergey Gonchar Add
Graphics Programmer (Flash Stage3D, interested in Direct3D11)
Dmitry Ivanov (jimon) Add
tech. lead in tatemgames.com (ios, android, win, mac, ps vita)
Dmitriy Vovk (StiX) Add
Crytek

Sergey Gonchar: @All
Скажите пожалуйста, почему на мобилах сначала идет тест глубины и только потом тест по трафарету? Имеется ввиду OpenGL ES 2.0. Я вот тут начитался всякого и выяснил что при tile-based рендеринг архитектуре, которая сейчас почти в каждой мобиле, сначала делать тест по трафарету дороже. Почему?

jimon: reply @Sergey Gonchar
тайловый движок может делать Z отсечение без Z buffer’а
и без растеризации

jimon: reply @Sergey Gonchar
а чтобы тест по трафарету выполнить нужно растеризировать геометрию

Crio: reply @jimon
а где можно почитать, что такое тайловый движок?

jimon: reply @Crio
хм, не видел чтобы его нормально описывали кроме приватных док
по-сути вот идет геометрия на рендер, в пк гпу дальше идет пиксельный шейдер, растеризация, пиксельный (грубо говоря)
а в tile-based, весь экран поделён сеткой на большие квадраты (32 на 32 пикселя обычно), вся геометрия перед вертексным шейдером бьется на пачки кто в какой квадрат попадает

StiX: reply @jimon
обычно тайлы 16х16. их фиксированное кол-во, в железе

jimon: reply @Crio
дальше в каждом квадрате хитрая железка сортирует треугольники (в powervr sgx до 72 за раз) и понимает что как кого перекрывает и что надо рисовать, она это понимает без растеризации
и только те что надо рисовать она отправляет в вертесный шейдер и дальше на растеризацию
это Z test без Z буффера, отсюда сумашедшая экономия ресурсов, доступные расширения 2048*1536 и тд и тп
но всё это живет только на непрозрачной геометрии, как только вы включаете блендинг всё идет п*здой
ой напутал, вертексный шейдер идет до тайлового движка конечно же

StiX: reply @jimon
HSR
только оно не сортирует

StiX: reply @jimon
а тупо рейкастит
в железе
в итоге не надо сортировать не прозрачную геометриую от блежнего к дальнему (как на РС) – нагрузка будет та же

StiX: reply @jimon
на ПВР”ах з буффер все равно есть
только он на самих тайлах гпу
упакован вместе с стенсил буфером

Sergey Gonchar: reply @StiX
Спасибо большое! Но мне все-равно остается непонятным один момент. Получается, что сначала вершинный шейдер, потом бьется все на тайлы и отбрасывается лишнее, растеризация и фрагментный шейдер, и ведь только потом идут тесты глубины и стенсила. То все-равно непонятно в чем разница? Тут видимо присутствует какая-то особенность внутренней реализации всей системы?

Sergey Gonchar: reply @Sergey Gonchar
тайлы растерезируются все вместе? или каждый тайл растеризируется отдельно от всех остальных?

jimon: reply @Sergey Gonchar
отдельно от всех по-идее

StiX: reply @Sergey Gonchar
каждый тайл является независимым

jimon: reply @Sergey Gonchar
без тайлов тебе надо растеризировать всю геометрию, делать z test и тд, а с тайлами тебе надо растеризировать и делать z test только несколько раз (по-сути эквивалентно overdraw)

Simon Kozlov: reply @jimon
Т.е. она таки без zbuffer в тайле растеризует? Т.е. на каждый пиксель pixel shader прогоняется один раз?

jimon: reply @Simon Kozlov
ну это в идеальной ситуации
на деле 1.5-2 раза прогоняется пиксельный шейдер на пиксель экрана
+ каждый раз с блендингом

Simon Kozlov: reply @jimon
Почему? Если вся геометрия opaque

jimon: reply @Simon Kozlov
тайловый двигло не идеальный
в абстрактно-идеальной ситуации он резолвит только 72 треугольника
а их может быть больше
а может а может и тд )

Simon Kozlov: reply @jimon
И что происходит, когда их больше?

jimon: reply @Simon Kozlov
результат растеризируется и отрисовывается
и берётся новая порция данных
ну там чуть сложнее чем просто конвеер, есть промежуточный буфер мегабайт в 16 куда складываются аттрибуты всей геометрии
но по-сути никакой магии, FLOPSы маленькие, ipad3 тянет всего 3x overdraw с 60 фпс

Simon Kozlov: reply @jimon
Не, ну погодь, тогда нужен локальный zbuffer для тайла

StiX: reply @Simon Kozlov
Он там и есть – на каждом тайле есть своя память, в которой хранится упакованный буфер глубины и стенсила
a HSR – это хардварный early z

Simon Kozlov: reply @jimon
Чтобы новый батч и старый батч совместить
Ну вот оказалось 100 треугольников в тайле
Ты взял первые 72, отсортировал, вывел
А чтобы совместить их с оставшимися- нужна z-инфорация

jimon: reply @Simon Kozlov
ну пойдет на растеризатор N примитивов с первого батча
потом M примитивов с второго батча
а дальше z test уже через z buffer
его ведь никто не отменял

Simon Kozlov: reply @jimon
То есть таки zbuffer есть?

jimon: reply @Simon Kozlov
ну да

Simon Kozlov: reply @jimon
Ок, тогда я все понимаю

jimon: reply @Simon Kozlov
самое весёлое это как альфа тест на это всё ложится

jimon: reply @Simon Kozlov
тут как бы люди оптимизировали, параллельно всё

jimon: reply @Simon Kozlov
а альфа тест форсит флаш каждой стадии конвеера, от вертексного шейдера до фрагментного

Simon Kozlov: reply @jimon
Т.е. треугольник с альфатестом рисуется честно в zbuffer, без этого HSR?

jimon: reply @Simon Kozlov
ага

Simon Kozlov: reply @jimon
Батчем по одному треугольнику?

jimon: reply @Simon Kozlov
ага
батчем по 1 треугольнику так же в растеризаторе
но там есть всё же z test перед фрагментным шейдером, альфатест в отличии от альфабленда требует записи в z буффер после фрагментного шейдера

Simon Kozlov: reply @jimon
И вот этот крутой HSR тест – он только для треугольников в этом батче, да?

Simon Kozlov: reply @jimon
Т.е. он не умеет умно пересекать с существующим zbuffer’ом, только треугольники между собой

jimon: reply @Simon Kozlov
ну да, фишка в том что тайловый движок не растеризирует

This happened on #gamedeff