Показать сообщение отдельно
Старый 09.12.2007, 02:30      #33
a2z
Супер-Модератор
 
Аватар для a2z
По умолчанию

Batch! Batch! Batch!

Так развернулась борьба за то, чтобы делать как можно больше с помощью как можно меньшего количества вызовов драйвера отрисовки. Каждый такой вызов передает GPU целый пакет (batch) треугольников, и чем таких пакетов меньше (а треугольников в них, соответственно, больше) – тем лучше. Особенности пакетной обработки раскрыты в ставшей уже классической презентации Nvidia под названием Batch! Batch! Batch!, где было наглядно продемонстрировано, что львиная доля процессорного времени уходит только на обработку вызовов драйвера (фактически, всего лишь тысяча вызовов в кадре «съедает» треть производительности Pentium IV 3 ГГц), и даны рекомендации, как эту долю понизить.

Эта борьба перенесла фокус оптимизации движка с удаления скрытых поверхностей на уменьшение количества обращений к драйверу и сокращение объема передаваемой от CPU к GPU информации. Конечно, HSR по-прежнему имеет большое значение, и народная мудрость «самые быстрые полигоны – те, что не отрисовываются» не потеряла своей актуальности и сегодня. Однако теперь зачастую правильнее отправить «оптом» сотню-другую лишних треугольников, чем тратить время CPU на их выявление и удаление, заставляя GPU в это время курить и разглядывать журналы в абсолютном бездействии.

Справка: Удаление скрытых поверхностей
Спойлер
Цель любого алгоритма удаления скрытых поверхностей состоит в том, чтобы время, затраченное на удаление невидимых частей окружения, было как можно меньше времени, необходимого на то, чтобы эти части сцены нарисовать. Возьмем, к примеру, простейшую 3D-сцену.

gfx-05.jpg
Простейшая 3D-сцена со стороны и с точки зрения камеры.

gfx-06.jpg
Белый конус камере не виден, так что и рисовать его не надо.

Легче всего отбросить те объекты, которые находятся позади камеры или по бокам, а также выше и ниже поля ее зрения: умножение на матрицу, несколько сравнений – и готово. Но если объектов много (тысячи, десятки тысяч), то это уже может быть проблемой, потому что потребует больших затрат процессорного времени. Чтобы отбрасывать объекты, части ландшафта или архитектуры уровня максимально эффективно, их объединяют в иерархии – так, что если при проверке отбрасывается верхний узел иерархии, то подчиненные ему узлы и объекты отбрасываются тоже. По этому общему принципу работают знаменитые благодаря хитам id Software BSP-деревья, восьмеричные деревья (octrees), порталы и их многочисленные вариации и комбинации.

gfx-07.jpg
Появление стены сильно усложняет задачу: цилиндр, куб и шар по-прежнему перед камерой, но рисовать их теперь не нужно.

Но отбросить то, что не попадает в поле зрения камеры, – это самая легкая задача. Гораздо труднее выявить объекты, которые будут заслонены другими объектами. Классический пример – камера смотрит в стену, за которой что-то есть. Если мы нарисуем и стену и объект за ней, то благодаря Z-буферу, в котором хранятся дальности всех пикселей изображения, картинка будет правильной, независимо от того, что мы вывели на экран сначала – объект или стену перед ним. Но при этом будет затрачено много лишнего времени на рендеринг объекта, которого на самом деле не видно.

Самый простой выход – отсортировать объекты по дальности и сначала выводить те, что ближе всех. Тогда при попытке нарисовать фрагмент, который на самом деле не виден, умный GPU (а они сейчас все умные) сверится с Z-буфером и отбросит его, сэкономив время шейдерных модулей и растеризаторов. Можно сначала нарисовать сцену только в Z-буфер – это гораздо быстрее, чем рендерить ее в цвете и дает возможность определить, какие объекты не видны совсем, чтобы при рабочем проходе их и не рисовать. Есть и другие методики, основанные на взаимодействии CPU и GPU, но основная тенденция состоит в том, что видеокарты стали значительно больше помогать в удалении скрытых поверхностей и большую часть самой тяжелой работы (например, отбрасывание полигонов на обратной стороне видимых объектов, которое процессору просто бессмысленно поручать) берут на себя, поэтому HSR из основной проблемы превратилось во второстепенную.

Однако и здесь DirectX 10 может быть полезен: с его помощью можно реализовать методику под названием predicated rendering, когда перед рендерингом сложного объекта сначала проверяется будет ли видима окружающая его «коробка» (bounding box) или ее полностью заслоняют лежащие ближе детали архитектуры. Predicated rendering можно было использовать и под DX9, но в DX10 такая методика практически не требует участия центрального процессора, а значит, на порядок более проста и эффективна.

gfx-08.jpg
Пример predicated rendering: сложный объект рисуется только после проверки видимости bounding box

gfx-09.jpg
Если выяснится, что «коробок» заслонен, какой смысл тратить время на отрисовку объекта?
Как движки работают теперь? Во-первых, центральный процессор сейчас уже очень редко изменяет геометрию – он лишь двигает «кости», а за то, чтобы «плоть» объектов двигалась вслед за костями, отвечает исключительно видеокарта, запрограммированная с помощью соответствующих вершинных шейдеров (vertex shaders). Это позволяет не только разгрузить CPU от этой несвойственной ему «глупой» работы, но и передавать геометрию персонажей в память видеокарты всего один раз при загрузке уровня, что очень благотворно влияет на производительность.

Во-вторых, разработчики все активнее стараются использовать механизм instancing, позволяющий отрисовывать множество идентичных объектов всего за один вызов драйвера. Именно благодаря instancing мы можем любоваться травой и густыми лесами, которые созданы путем тысячекратного повторения нескольких шаблонных деревьев или кустиков травы, причем для отображения этих тысяч зеленых насаждений необходимо всего несколько (а иногда даже один) вызовов рендеринга. Ясное дело, при этом мы рискуем отправить на отрисовку несколько десятков лишних кустов, которые будут заведомо не видны, но это не скажется отрицательно на производительности – тем более что современные GPU обладают развитыми средствами удаления невидимой геометрии и до «дорогостоящего» этапа растеризации лишние объекты, скорее всего, даже не дойдут.

В теории все звучит замечательно, но если применять такой подход на практике под DirectX 9, то быстро обнаружится несколько подводных камней. Главная проблема в том, что все эти идентичные объекты, которые мы выводим на экран «одним махом», – они такие… идентичные. Возможности придания им индивидуальности крайне ограничены.
a2z вне форума Пол: Мужчина   Ответить с цитированием Вверх
Благодарности: 5
Andrew (09.12.2007), kellan (09.12.2007), MuR (18.08.2008), Сергей Копылов (09.12.2007), Soul of a tiger (09.12.2007)