Важные изменения в Direct3D 12 по сравнению с Direct3D 11

Direct3D 12 представляет собой существенный отход от модели программирования Direct3D 11. Direct3D 12 позволяет приложениям быть ближе к оборудованию, чем когда-либо прежде. Благодаря приближению к оборудованию Direct3D 12 быстрее и эффективнее. Но компромисс вашего приложения с увеличением скорости и эффективности с Direct3D 12 заключается в том, что вы отвечаете за больше задач, чем с Direct3D 11.

Direct3D 12 — это возврат к низкоуровневой программе; он дает вам больший контроль над графическими элементами игр и приложений, предоставляя новые функции: объекты для представления общего состояния конвейера, списки команд и пакеты для отправки работы, а также кучи дескриптора и таблицы для доступа к ресурсам.

В Direct3D 12 ваше приложение повысило скорость и эффективность, но вы отвечаете за больше задач, чем с Direct3D 11.

Явная синхронизация

  • В Direct3D 12 синхронизация ЦП и GPU теперь является явной ответственностью приложения и больше не выполняется неявно средой выполнения, как в Direct3D 11. Это также означает, что Direct3D 12 не выполняет автоматическую проверку на наличие рисков конвейера, поэтому, опять же, это ответственность приложений.
  • В Direct3D 12 приложения отвечают за обновление данных по конвейеру. То есть шаблон Map/Lock-DISCARD в Direct3D 11 должен выполняться вручную в Direct3D 12. В Direct3D 11, если GPU по-прежнему использует буфер при вызове ID3D11DeviceContext::Map с D3D11_MAP_WRITE_DISCARD, среда выполнения возвращает указатель на новую область памяти вместо старых данных буфера. Это позволяет GPU продолжать использовать старые данные, пока приложение помещает данные в новый буфер. В приложении не требуется дополнительное управление памятью; старый буфер повторно используется или уничтожается автоматически после завершения работы с GPU.
  • В Direct3D 12 все динамические обновления (включая буферы констант, динамические буферы вершин, динамические текстуры и т. д.) явно контролируются приложением. Эти динамические обновления включают все необходимые ограждения GPU или буферизацию. Приложение отвечает за сохранение доступной памяти до тех пор, пока она больше не будет нужна.
  • Direct3D 12 использует подсчет ссылок в стиле COM только для времени существования интерфейсов (с использованием слабой эталонной модели Direct3D, привязанной к времени существования устройства). Все сроки существования памяти ресурсов и описания относятся к исключительной ответственности приложения за надлежащее время хранения и не учитываются. Direct3D 11 также использует подсчет ссылок для управления временем существования зависимостей интерфейса.

Управление местом расположения физической памяти

Приложение Direct3D 12 должно предотвращать гонки между несколькими очередями, несколькими адаптерами и потоками ЦП. D3D12 больше не синхронизирует ЦП и GPU, а также не поддерживает удобные механизмы переименования ресурсов или много буферизации. Необходимо использовать ограждения, чтобы избежать перезаписи памяти несколькими единицами обработки, прежде чем другой блок обработки завершит ее использование.

Приложение Direct3D 12 должно гарантировать, что данные хранятся в памяти, а GPU считывает их. Память, используемая каждым объектом, становится резидентной во время создания объекта. Приложения, которые вызывают эти методы, должны использовать ограждения, чтобы гарантировать, что GPU не будет обращаться к вытеснили объекты.

Барьеры ресурсов — это еще один тип синхронизации, используемый для синхронизации переходов ресурсов и подресурсов на очень детализированном уровне.

См. раздел Управление памятью в Direct3D 12.

Объекты состояния конвейера

Direct3D 11 позволяет управлять состоянием конвейера с помощью большого набора независимых объектов. Например, состояние входного ассемблеров, состояние шейдера пикселей, состояние растеризатора и состояние слияния выходных данных можно изменять независимо. Такая конструкция обеспечивает удобное и относительно высокоуровневое представление графического конвейера, но не использует возможности современного оборудования, в первую очередь потому, что различные состояния часто являются взаимозависимыми. Например, многие GPU объединяют пиксельный шейдер и состояние слияния выходных данных в единое аппаратное представление. Но так как API Direct3D 11 позволяет задавать эти этапы конвейера отдельно, драйвер отображения не может устранить проблемы с состоянием конвейера, пока состояние не будет завершено, а это не до времени отрисовки. Эта схема задерживает настройку состояния оборудования, что означает дополнительные накладные расходы и меньшее количество вызовов рисования на кадр.

Direct3D 12 решает эту схему, объединяя большую часть состояния конвейера в неизменяемые объекты состояния конвейера (PSOS), которые завершаются после создания. Затем оборудование и драйверы могут сразу же преобразовать PSO в любое аппаратное собственное инструкции и состояние, необходимые для выполнения работы с GPU. Вы по-прежнему можете динамически изменять используемый PSO, но для этого оборудованию нужно только скопировать минимальный объем предварительно вычисленного состояния непосредственно в аппаратные регистры, а не вычислять состояние оборудования в режиме реального времени. Благодаря psos затраты на вызовы draw значительно сокращаются, и в кадре может выполняться гораздо больше вызовов рисования. Дополнительные сведения о ППО см. в статье Управление состоянием графического конвейера в Direct3D 12.

Списки команд и пакеты

В Direct3D 11 вся отправка работы выполняется через непосредственный контекст, который представляет собой единый поток команд, которые отправляются в GPU. Для достижения многопоточного масштабирования игры также имеют отложенные контексты , доступные для них. Отложенные контексты в Direct3D 11 не идеально сопоставляются с оборудованием, поэтому в них можно выполнить относительно мало работы.

В Direct3D 12 появилась новая модель отправки работ на основе списков команд, содержащих всю информацию, необходимую для выполнения определенной рабочей нагрузки на GPU. Каждый новый список команд содержит такие сведения, как использование PSO, необходимые ресурсы текстуры и буфера, а также аргументы для всех вызовов draw. Так как каждый список команд является автономным и не наследует состояние, драйвер может предварительно вычислить все необходимые команды GPU заранее и в свободном потоке. Единственный необходимый последовательный процесс — это окончательная отправка списков команд в GPU через очередь команд.

В дополнение к спискам команд в Direct3D 12 также представлен второй уровень предварительного вычисления: пакеты. В отличие от списков команд, которые являются полностью автономными и обычно создаются, отправляются один раз и отклоняются, пакеты предоставляют форму наследования состояния, которая позволяет повторно использовать. Например, если игра хочет нарисовать две модели персонажей с разными текстурами, один из подходов — записать список команд с двумя наборами одинаковых вызовов draw. Но другой подход заключается в том, чтобы "записать" один пакет, который рисует одну модель символов, а затем "воспроизвести" пакет дважды в списке команд с помощью разных ресурсов. В последнем случае драйверу дисплея нужно вычислить соответствующие инструкции только один раз, а создание списка команд фактически равносильно двум недорогим вызовам функций.

Дополнительные сведения о списках команд и пакетах см. в разделе Отправка работы в Direct3D 12.

Кучи и таблицы дескрипторов

Привязка ресурсов в Direct3D 11 очень абстрагирована и удобна, но оставляет многие современные возможности оборудования недостаточно используемыми. В Direct3D 11 игры создают объекты представлений ресурсов, а затем привязывают эти представления к нескольким слотам на различных этапах шейдера в конвейере. Шейдеры, в свою очередь, считывают данные из тех слотов явной привязки, которые фиксируются во время рисования. Эта модель означает, что каждый раз, когда игра рисует с использованием разных ресурсов, она должна повторно привязать различные представления к разным слотам и снова вызвать draw. Этот случай также представляет собой издержки, которые можно устранить, полностью используя возможности современного оборудования.

Direct3D 12 изменяет модель привязки в соответствии с современным оборудованием и значительно повышает производительность. Вместо того, чтобы требовать автономных представлений ресурсов и явного сопоставления со слотами, Direct3D 12 предоставляет кучу дескрипторов, в которой игры создают различные представления ресурсов. Эта схема предоставляет графическим процессорам механизм для непосредственной записи описания ресурса (дескриптора) аппаратного обеспечения в память. Чтобы объявить, какие ресурсы должны использоваться конвейером для определенного вызова draw, игры указывают одну или несколько таблиц дескрипторов, представляющих поддиапазоны полной кучи дескрипторов. Так как куча дескрипторов уже заполнена соответствующими данными дескриптора оборудования, изменение таблиц дескрипторов является чрезвычайно экономичной операцией.

Помимо повышения производительности, предоставляемой кучами дескрипторов и таблицами, Direct3D 12 также позволяет динамически индексировать ресурсы в шейдерах, что обеспечивает беспрецедентную гибкость и открывает новые методы отрисовки. Например, современные механизмы отложенной отрисовки обычно кодируют какой-либо идентификатор материала или объекта в промежуточный g-буфер. В Direct3D 11 эти подсистемы должны быть осторожны, чтобы избежать использования слишком большого количества материалов, так как включение слишком большого количества в одном g-буфере может значительно замедлить окончательный проход отрисовки. Благодаря динамически индексируемым ресурсам сцена с тысячей материалов может быть завершена так же быстро, как и сцена с десятью.

Дополнительные сведения о кучах и таблицах дескрипторов см. в разделах Привязка ресурсов и Различия в модели привязки от Direct3D 11.

Перенос из Direct3D 11

Перенос из Direct3D 11 — это вовлеченный процесс, описанный в разделе Перенос из Direct3D 11 в Direct3D 12. Также обратитесь к диапазону параметров в разделе Работа с Direct3D 11, Direct3D 10 и Direct2D.

Основные сведения о Direct3D 12