Встречаем DirectX 10
Многие люди в свободное время играют в компьютерные игры. И получают немало удовольствия. Частично в этом “повинен” и DirectX 9. Действительно, мы играем в игры, разработанные под интерфейс прикладного программирования (API) DirectX 9 ещё в декабре 2002 года. Почти четыре года назад. И хотя многие подразумевают под словом “DirectX” только графику, в стандарт DirectX на самом деле входят разные API, отвечающие за различные игровые аспекты, из которых графика – только один. Популярные игры, такие, как Half-Life 2, F.E.A.R., Battlefield 2 и Oblivion, используют самую последнюю версию DirectX, а именно 9.0c.
В DirectX три ключевые области: устройства ввода, звук и видео. В следующей таблице приведён список API в последней версии DirectX.
Устройства ввода | |
DirectInput | API для устройств ввода, включая клавиатуры, мыши, джойстики, гейм-пады и устройства с силовой отдачей. В данной версии API поддерживаются функции контроллера Xbox360 при подключении к ПК с Windows XP SP1 или более поздней версией. |
Звук | |
DirectSound | Низкоуровневый аппаратный API, который служит интерфейсом между приложениями и звуковой картой. Через этот API можно управлять аппаратными буферами, громкостью, высотой тона и позиционированием отдельных звуков. |
DirectMusic | Высокоуровневый API, способный смешивать множество звуков. Он может воспроизводить MIDI, а также различные звуки с индивидуальными уровнями громкости и другими параметрами. |
Видео | |
Direct3D | API, благодаря которому на вашем экране появляется изображение. Это низкоуровневый интерфейс, который позволяет обрабатывать 3D-объекты с помощью аппаратных ускорителей (видеокарт). |
DirectDraw | Раньше этот API был очень важен, но в текущей версии обработка 2D-функций была перенесена в Direct3D. |
В оставшейся части статьи мы поговорим о том API, который интересует большинство людей: Direct3D. И здесь с появлением DirectX 10 нас ждёт немало перемен. В Direct3D 10 появятся новые функции, призванные решить существующие графические проблемы, а также инструменты, позволяющие заняться новыми задачами рендеринга. Кроме того, 3D-конвейер будет упрощён, что тоже должно способствовать появлению лучших и более эффектных игр.
Что изменилось?
В октябре, после пленарного доклада по поводу DX10 на мероприятии nVidia, мы смогли поговорить с Дэвидом Блюфом (David Blythe), software-архитектором Microsoft Graphics Platform Unit по DirectX 10. Он прочитал доклад о важных улучшениях, сделанных в Direct3D 10. Разработчики ПО и производители “железа” уже давно накопили немалый багаж проблем, и, по словам Блюфа, Direct3D 10 решает большинство проблем и жалоб.
Direct3D 10 отличается пятью ключевыми изменениями:
- улучшенные возможности программирования (Shader Model 4.0 и геометрические шейдеры);
- строгие аппаратные спецификации;
- улучшенная производительность (снижение числа обрабатываемых команд на кадр);
- унифицированные наборы инструкций (HLSL 10);
- потоковый ввод/вывод (геометрический шейдер может записывать в память).
Позвольте привести графическую диаграмму конвейера Direct3D 10, которая показывает, как происходит рендеринг изображения. Она позволит отследить новые изменения.
Слайд презентации “The Direct3D 10 System” от David Blythe.
С появлением линейки ATi Radeon X1000 концепция традиционного конвейера ушла в историю. Теперь говорить о том, что карта обладает каким-то числом пиксельных конвейеров совершенно бессмысленно. Просто выкиньте слово “пиксельные конвейеры” из головы, если только вы не рассматриваете устаревшие карты.
Улучшенные возможности программирования
Одна из проблем при разработке игры заключается в том, чтобы перенести мысли и видение художника на экран компьютера. Человек в уме может представить любую абстрактную картинку, содержащую все те детали, которые мы встречаем в окружающем мире. Компьютерная графика – совершенно другое дело, поскольку логика нашего мозга намного более динамична и выразительна, чем у компьютера. Кремний всегда будет таким, каким его сделали на полупроводниковом заводе. И так было до появления программируемых шейдеров. Впрочем, программируемые шейдеры – всего лишь один из компонентов движка рендеринга. Здесь есть другие ограничения: что-то может быть вычислено, а что-то нет. Так что вычислительная мощность всегда чем-то ограничивается.
По мере того, как росли потребности программистов, появлялись новые стандарты как в аппаратных реализациях, так и в программировании. Перед нами очередной виток эволюции, и новый Direct3D вновь поднимает планку возможностей шейдеров.
Ниже представлена таблица, в которой приведены изменения в модели шейдеров. Мы не будем углубляться в детали. В двух словах: Shader Model 4.0 (SM 4.0) намного более продвинутая модель, чем предыдущая версия. Кроме того, можно смело прощаться с концепцией разделения шейдеров на пиксельные и вершинные. Шейдеры с фиксированными функциями остались в прошлом.
Строгие аппаратные спецификации
Между аппаратными дизайнами ATi и nVidia существует ощутимое различие. И одна из жалоб программных разработчиков касалась слишком большой разницы в возможностях аппаратных дизайнов, в результате чего в играх появлялись несколько путей кода, а на экране – разная по качеству картинка для разных видеокарт. Например, если игра определяет старую видеокарту, она запустит специальный путь кода, который сможет дать нормальные fps в этой игре за счёт уступок в качестве картинки. Вы можете посмотреть это на примерах в нашей статье, посвящённой разнице в качестве графики.
Разработчики игр под приставки избавлены от этой проблемы, поскольку архитектура графической подсистемы жёстко обозначена. Но, к сожалению, разработчики игр под ПК такой роскоши не имеют. Если у них и созрели в уме новые идеи и техники, которые они желали бы видеть в игре, то после реализации остаётся только надеяться, что игра пойдёт на современном “железе” именно с тем путём кода, который продемонстрирует все фантастические функции. Но, как мы знаем по опыту, большинство геймеров играют не с максимальным количеством возможных визуальных функций. По причине как старого “железа”, так и желания принести качество в жертву более высоким fps.
Что ещё хуже, в DirectX 9 некоторые части стандарта были слишком свободны для трактовки, а некоторые части были вскоре изменены и не успели утвердиться в дизайнах ATi и nVidia. В результате в стане разработчиков возникла определённая путаница, скажем, касающаяся разных стандартов точности вычислений у конкурирующих производителей “железа”. Последним пришлось учить разработчиков сильным сторонам и возможностям своих видеокарт. В целом, конфликт стандартов отнюдь не ускорил появление качественных игр на рынке.
Direct3D 10 определяет стандарты на требуемый набор функций, число доступных ресурсов, точность вычислений и разные форматы хранения. Если внутри “железа” Direct3D 10 всё должно быть 32-битным (как в целых числах, так и с плавающей запятой), форматов хранения будет несколько. Ниже они приведены.
В списке можно видеть и полные форматы одинарной точности, и форматы с половинной точностью, например, unorm и snorm16. float16 используется для таких функций, как HDR-освещение, но его недостатком можно считать слишком большой объём и требования к пропускной способности. Были созданы другие альтернативные форматы, например, 11-11-10. Это комбинация двух блоков float11 и одного float10 (11 на красный, 11 на зелёный и 10 на синий) на 32 бита вместе с форматом с общей экспонентой (RGBE). Здесь приведена более подробная информация по форматам и точности вычислений с плавающей запятой в рамках стандарта IEEE 754 .
Фиксированные функции или унифицированная архитектура?
Ещё один плацдарм для свободной трактовки под DirectX 9 касался подходов ATi и nVidia. ATi решила разделить традиционный конвейер, чтобы дать больший набор функций при прежних ограниченных ресурсах. nVidia же решила придерживаться в своей архитектуре традиционного фиксированного дизайна.
Нет ничего необычного в том, чтобы оснастить карту X блоками вершинных шейдеров, Y блоками пиксельных шейдеров и Y блоками растровых операций (ROP), но, как доказала ATi с последними графическими процессорами DirectX 9.0c, динамическое ядро позволяет достичь более высокой производительности. Многие разработчики игр специально переделали новинки, чтобы они смогли использовать всю мощь пиксельных шейдеров раздельного дизайна. А ATi смогла выгодно прорекламировать увеличенное число блоков пиксельных шейдеров у новых видеокарт. Архитектура стандарта Direct3D 10 могла бы следовать традиционным блокам шейдеров с фиксированными функциями, но смысл?
Если nVidia публично и не разглашает структуру процессора G80, то ATi давно уже говорит о ядре с унифицированными шейдерами. Они действительно весьма важны, поскольку унифицированные шейдеры позволяют менять функции “на лету”. Скажем, если в кадре требуется больше мощности вершинных шейдеров, либо мощности пиксельных шейдеров, ядро может выделить на соответствующие нужды большее число вычислительных блоков, чтобы задача была выполнена максимально быстро.
Ниже показано несколько примеров нагрузки в “традиционном” окружении (мы пошли на некоторые допущения, чтобы сделать схему более понятной).
Пример 1. Тяжёлая нагрузка на блоки вершинных шейдеров, лёгкая – на блоки пиксельных шейдеров.
В данном примере блоки пиксельных шейдеров нагружены не полностью. Они могли бы сделать для кадра и больше работы, но, к сожалению, всё упирается в загруженность блоков вершинных шейдеров.
Пример 2. Лёгкая нагрузка на блоки вершинных шейдеров, тяжёлая – на блоки пиксельных шейдеров.
Здесь ситуация обратная. Блоки вершинных шейдеров недогружены, а пиксельных шейдеров – перегружены.
Пример 3. Тяжёлая нагрузка на блоки вершинных шейдеров, лёгкая – на блоки пиксельных шейдеров.
Здесь блоки пиксельных шейдеров выполняют те же вычисления, что и в первом примере, но зато ещё 12 блоков выполняют дополнительные вершинные вычисления. В итоге графическое ядро работает на полную мощность.
Пример 4. Лёгкая нагрузка на блоки вершинных шейдеров, тяжёлая – на блоки пиксельных шейдеров.
В последнем примере нагрузка на блоки вершинных шейдеров такая же, как в примере 2, но под пиксельные вычисления отводится ещё 6 дополнительных блоков.
Цель нашей демонстрации – показать, что шейдеры, это всего лишь программы, работающие на процессорах. С появлением нового стандарта Direct3D 10 было совершенно бессмысленно придерживаться фиксированной архитектуры шейдеров. С умной логикой и сильным ядром мы должны получить существенные преимущества от унифицированных архитектур, пусть даже с тем же числом вычислительных блоков, что у фиксированной архитектуры.
Дополнительные улучшения
Ещё одна жалоба разработчиков и производителей “железа” по поводу предыдущих версий Direct3D касалась слишком большой зависимости от ресурсов CPU. Графика – это всего лишь подсистема компьютера. И графический, и центральный процессоры ПК опираются на одни и те же ресурсы, например, на подсистему ОЗУ. Кроме того, видеокарте приходится обращаться к CPU за координацией и инструкциями. Наконец, если требуется просчитать сцену со сложной или динамической геометрией, то тоже приходится опираться на вычислительные ресурсы CPU. Это, опять же, сказывается на производительности.
Можно лучше обрабатывать ошибки и исключения, лучше распределять ресурсы и контролировать доступ к ним, даже оптимизировать язык шейдеров. Но основная проблема кроется не в этом. Как поведал Блюф, внутренняя структура API за последние десять лет менялась незначительно. Были выделены три причины, приводящие к лишним вычислениям:
- недопонимание требований приложения;
- различные стили обработки;
- несоответствие между API и “железом”.
Первую и вторую причину решить можно. Более строгие стандарты между производителями “железа” и разработчиками ПО решают первую проблему, а вторая находится в руках разработчиков.
Набор примеров DX10, которые используются в тестах Microsoft.
Последняя проблема наиболее серьёзная. Команда разработчиков DX10 решила перейти от отдельных взаимодействий к более крупным моделям и описать для них возможные состояния. В результате удалось сократить число вызовов API. В следующей таблице приведены примеры.
Операции/число команд | Direct3D 9 | Direct3D 10 |
Draw | 1470 | 154 |
Bind VS Shader | 6636 | 416 |
Set Constant | 3297 | 916 |
Set Blend Function | 787 | 530 |
В таблице приведена разница между числом операций у Direct3D 9 и 10 по результатам анализа Блюфа. На системе Intel Pentium 4, которую использовали разработчики, число вызовов прорисовки (draw) было уменьшено в десять раз. Снижение вычислительных операций в драйвере освобождает ресурсы CPU для других, более важных задач. А также снижает зависимость рендеринга от CPU. В результате процессор может лучше просчитывать искусственный интеллект, физику, либо на сцене можно располагать большее число объектов.
Ещё одно важное улучшение появилось в форме Microsoft Instancing 2.0. Instancing вступает в силу, если на сцене есть большое число очень похожих объектов, которые нужно нарисовать, осветить, текстурировать и т.д. Под Direct3D 9 каждый объект в этой батарее требовал собственного вызова на рисование, добавляясь в программный стек и используя ресурсы CPU. Под Direct3D 10 все эти объекты можно вывести одним вызовом. Так что в грядущих играх мы наверняка увидим тысячи юнитов на поле битвы, что эффективно повышает реализм.
Скриншот Supreme Commander (THQ), на котором можно видеть более сотни юнитов в высоком разрешении.
Геометрические шейдеры и потоковый вывод
Слайд презентации “The Direct3D 10 System” от David Blythe.
Наконец, позвольте поговорить о новейшей части ядра: геометрических шейдерах (Geometry Shader, GS). Давайте пройдём через логические шаги процесса рендеринга (хотя с унифицированной архитектурой они весьма условны). Начнём с блока Input Assembler (IA). Как видно на диаграмме, блок IA получает вершинные данные.
Традиционно вершинные данные считываются последовательно из вершинного буфера, но можно использовать и индексный буфер. Последний обеспечивает дополнительную оптимизацию производительности, поскольку можно избежать повторного просчёта данных с тем же индексом.
IA также может копировать объекты, мы говорили об этом выше, когда рассматривали Instancing. Каждый объект получает ID индекс, по которому можно к нему обращаться на следующих ступенях. В результате, например, из одного танка в игре может получиться сотня клонов, каждый из которых будет обладать собственными свойствами и ID. Здесь, опять же, все объекты можно обработать одним вызовом вместо отдельных для каждого, как было раньше.
Слайд презентации “The Direct3D 10 System” от David Blythe.
От блока вершинных шейдеров данные переходят на новый блок геометрических шейдеров (Geometry Shader) и потокового вывода (Stream Output, SO). Блок GS получает все вершины (точки, линии и треугольники) и может их обрабатывать. По сути, блок GS может увеличивать число входных примитивов, создавая дополнительные: до 1024 32-битных значений вершинных данных. Это самая мощная часть ядра. Кроме того, блок GS может также добавлять дополнительные атрибуты к вершинным данным – или уничтожать их.
Блок геометрических шейдеров столь мощный, поскольку это единственный блок, который может писать в память через потоковый вывод (Stream Output). Эти данные могут считываться обратно, то есть блоки IA и вершинных шейдеров могут вообще прекратить снабжение данными. В итоге сцена может полностью просчитываться через данные потокового вывода.
Слайд презентации “The Direct3D 10 System” от David Blythe.
Остальная часть процесса нам знакома. Данные переходят на следующий этап, где производится растеризация и Z-отсечение. Затем происходит обработка на блоке пиксельных шейдеров, где на проволочный каркас накладываются текстуры. Сюда же входят освещение и другие техники, которые дают играм столь великолепный вид.
Заключение
Скриншот Crysis от Crytek.
Обсуждать новый стандарт Direct3D 10 и его потенциальное влияние на 3D-графику можно долго. Мы уже видели игру Crysis на картах DirectX10, и можно сказать только одно: впечатляет! Будущее игр определённо за DirectX 10, и если вы не заполучите в свою систему DX10-видеокарту, то многое упустите.
Для программистов переход с DirectX 9 на DX10 окажется относительно простым. Язык HLSL (High Level Shader Language) сегодня популярен, а перенос игры с DX9 на DX10 не должен оказаться сложным. Уже появились соответствующие утилиты и программы, которые окажутся на руку разработчикам.
Да, существует причина, по которой за последние несколько месяцев на рынке не появилось новых крупных проектов: все ждут DirectX 10. Что весьма приятно, DX10 может обеспечить прирост производительности и в существующих играх.
Обсудить статью в форуме THG.ru