Direct3D 10
Материал из Википедии — свободной энциклопедии
| Эту статью следует викифицировать.
Пожалуйста, оформите её согласно правилам оформления статей.
|
| Эта статья или раздел нуждается в переработке.
Пожалуйста, улучшите её в соответствии с правилами написания статей.
|
| Стиль этой статьи неэнциклопедичен или нарушает нормы русского языка.
Статью следует исправить согласно стилистическим правилам Википедии.
|
| Эта статья должна быть полностью переписана.
На странице обсуждения могут быть пояснения.
|
Direct3D 10 - набор API функций для взаимодействия с видеокартой. Доступен только на ОС начиная с Windows Vista, поддерживается аппаратно видеокартами класса NV GeForce 8x00, ATI Radeon 2x00 и выше.
Далее приведены ключевые особенности и отличия от DirectX версии 9.
[править] Новая driver model
В Windows Vista совершенно новая «driver model» — WDDM (Windows Display Driver Model, в девичестве LDDM — Longhorn Display Driver Model) — серьезное изменение в модели видео-драйвера со времен появления hardware acceleration. В XDDM (Windows XP Display Driver Model) каждый вызов DirectX добавлял токен в «command buffer» в независимом от видеокарты формате. Когда DX Runtime решал, что буфер достаточно заполнен, вызывалась функция драйвера (в kernel mode), которая получала этот буфер. После этого драйвер разбирал этот буфер и передавал данные видеокарте. То есть никаких функций драйвера в user mode не было. Развитие видеокарт и, как следствие, усложнение command buffer’а привело к тому, что драйвер стал немыслимо толстым и в случае любой ошибки провоцировал BSOD. Также в XDDM у OS нет ни способа установить приоритет, управлять видеопамятью, шедулить вызовы DX, что затрудняет разделение видеокарты между несколькими процессами — причина Device Lost.
В новой driver model сделано разделение между user mode и kernel mode частью драйвера. Все вызовы DX напрямую идут в user-mode driver, который готовит сразу hardware-dependent буфер. Этот буфер иногда передаёт в kernel, откуда он уже идёт на видеокарту. Таким образом вся тяжёлая работа выполняется в user-mode части, а в kernel пересылка собранного буфера в DMA-трансфер видеокарты. Как итог, если user-mode driver упадет, ничего страшного не случится — закроется конкретное приложение (но не BSOD). И у драйвера больше контроля (когда и сколько kernel-mode calls делать). Также DX Runtime становится совсем тонкий — нет command buffers, напрямую вызываются функции драйвера. Кроме этого между user-mode и kernel-mode частями есть GPU Scheduler, который выбирает какие собранные буфера отправлять видеокарте (разделение GPU на много процессов).
[править] Виртуализация видеопамяти
Теперь если не хватает видеопамяти, то ресурсы переносятся в системную (откуда могут быть отсваплены). За счёт наличия у Windows Vista контроля аллокаций видеопамяти (ранее, у драйвера) можно распределять её более эффективно, чем POOL_MANAGED в XDDM. На данном этапе это работает на программном уровне - GPU Scheduler перед передачей DMA-пакета карточке загружает все нужные текстуры в видеопамять (умеет подгружать их заранее, пока GPU занят другим и свободна шина). Если приложение fullscreen - все лишнее из видеопамяти будет перекинуто в системную по мере необходимости; если в windowed - разделение памяти между текущими процессами. Если требуется гарантировать 100% наличие ресурса в видеопамяти, то необходимо использовать fullscreen и контроль над размером аллокаций.
[править] Отсутствие Device Lost
В предыдущих версиях по различным причинам мог происходить Device Lost, после чего требовалось загружать все ресурсы в видеопамять заново и производить Restore объектов. С новой моделью драйвера этой проблемы больше не существует. Возможен только Device Removed, который означает что-то вроде "выдернули видеокарту"/"поставили новую версию драйвера" и встречается очень редко.
[править] Убраны капсы
В DX10 больше нет капсов, как таковых. Гарантируется наличие всей функциональности, то есть если карта поддерживает DX10, то она обязана держать последнюю версию шейдеров в полном объёме, поддерживать все форматы текстур, все возможные режимы фильтрации, стенсила и всего-всего-всего. Более того, для DX10 написали спецификацию правил растеризации, то есть теперь картинка на разных видеокартах на одинаковом коде всегда должна быть одинаковой и совпадать с эталонным софтверным растеризатором. Если это не так, то это баг производителя видеокарточки. В будущем новая функциональность будет появляться кусками, типа набор фич DX10.1, DX11 и т. д.
[править] Уменьшена стоимость вызова функций DirectX
Уменьшена стоимость вызова функций (в том числе DIP) на CPU. По данным презентаций Microsoft можно наблюдать 10x уменьшение стоимости. Это существенно, так как тяжёлая игра может проводить около 10+ миллисекунд в вызовах DX. Большую часть времени вызова ранее уходило на Runtime и Driver. теперь driver model фактически ничего не делает, а сразу предоставляет исполнение драйверу.
[править] State Objects и Constant Buffers
Появились State Objects - объекты, которые можно предварительно собрать при создании и потом быстро устанавливать на видеокарте. Добавлены Constant Buffers, позволяющие более эффективно выставлять константы шейдеров.
[править] Будет ли DX10 для Microsoft Windows XP?
Ответ очевиден - нет. Причина в том, что перенос новой драйверной модели невозможен - требуется слишком много изменений в ядре операционной системы. Если же переносить только набор новых функциональных возможностей DX10, то тоже возникают проблемы: виртуализацию и шедулинг невозможно осуществить в старой модели драйвера, перенос аппаратных возможностей - слишком большой объём работы для Microsoft и IHV.
[править] Буферы и биндинг
Для основных типов данных (вершин, индексов, констант) введён единый буфер - ID3D10Buffer - набор байтов в памяти. Type safe обеспечивается за счёт указания при создании содержимого буфера. Для ресурсов введены отдельные объекты для биндинга к конвейеру - resource views. То есть сначала создаем текстуру как объект в памяти, а потом её resource view как инпут для шейдера или как render target, и уже с этим view вызываем PSSetShaderResources (вместо SetTexture) и OMSetRenderTargets (вместо SetRenderTarget). Стоит отметить, что у одного ресурса view может быть несколько.
такой принцип позволяет работать обобщенно. Существуют typeless ресурсы, то есть ресурсы, которые не определённого типа (не указан при создании) - например, DXGI_FORMAT_R32G32B32_TYPELESS. Тип таких ресурсов выбирается во время создания view (например, DXGI_FORMAT_R32G32B32_UINT или DXGI_FORMAT_R32G32B32_FLOAT) и выбора элемента/слайса из массива текстур/объмной текстуры.
[править] Использование объектов-состояний
Все Set*State заменены на State Objects. Стейты разделены по нескольким группам:
- Rasterizer State - fill mode, cull mode, depth bias, multisample, scissor и т. д.
- Blend State - alpha blend, color write mask, blend op и т. д.
- Depth State - depth func, stencil func и т. д.
- SamplerState - tex filtering, clamping и т. д.
Стейты для каждой группы ставятся целиком, а не каждый по отдельности, как в D3D9. Для каждой группы можно создать State Object, которому при создании указывается полный набор стейтов группы, и "установить" можно только его. Создание State Object - дорогая и медленная операция и должна вызываться редко. Мотивация этого нововведения - такой API позволяет драйверу сгенерировать набор команд видеокарте заранее (при создании State Object) и не генерировать его каждый раз во время рендера при вызовах Set*State.
[править] Использование буферов констант
Set*ShaderConstant заменены на Constant Buffers - группы констант (буфер на n констант), устанавливающихся за раз. Группу можно локать и записывать как обычный буфер. Биндинг к шейдеру производится начиная с некоторого слота.
Таким образом использование констант сводится к разделению их на несколько групп по частоте обновления (per-object, per-material, per-pass, per-scene) и созданию для каждой группы Constant Buffer. Помимо дополнительной производительности такой подход даёт драйверу высокоуровневую картину - больше возможностей для оптимизации.
[править] Параметры шейдеров
VertexDeclaration заменён на Input Layout. Он требует при создании Shader Input Signature, то есть список input-параметров шейдера. Созданный объект можно использовать как Vertex Declaration с любым шейдером, имеющим такой же список input-параметров. В D3D9 Vertex Declaration устанавливался независимо от шейдера при рендере и поэтому драйверам приходилось серьёзно модифицировать сетап при смене vdecl. Сейчас vdecl жёстко привязан ко входу шейдера, что позволяет драйверу предвычислять все заранее.
[править] Убраны asm-шейдеры
Шейдеры больше нельзя писать на асме - нужно пользоваться HLSL. Хотя ассемблер для shader model 4.x есть и можно смотреть результат компиляции шейдеров в него, но больше нет возможности получить бинарный код шейдера из текста асма (то что делали psa.exe/vsa.exe). Отреверсинженирить бинарный код, впрочем, никто не мешает.
[править] Компилятор HLSL 4.0
Чтобы было легче портировать код шейдеров, компилятор умеет компилять HLSL-шейдеры старых версий (SM2.0, SM 3.0) в SM4.0. В новом HLSL добавили атрибуты для хинтов компилятору - unroll для лупов и выбор dynamic vs static branching для условных переходов.
[править] Геометрические шейдеры
Geometry Shader - это дополнительный шейдер между вершинным (Vertex Shader) и пиксельным (Pixel Shader), который может генерировать примитивы. На вход ему подается примитив с информацией о соседях, на выход - можно сгенерировать несколько (не фиксированное число). Основная идея - наконец генерировать геометрию на GPU. Geometry Shaders очень плохо подходят для тесселяции и нужны для всяческой локальной генерации геометрии по мелочи. Например, можно патикл строить по одному вертексу или использовать стрипы геометрии в post-processing (например, в motion blur - из карты скоростей генерировать геометрические линии, по которым блурится картинка (так делает Lost Planet)). Совсем из другой области - например, делать рендер в Cubemap за один проход, GS выясняет в какие стороны cubemap попадает треугольник, и разбивает его на несколько. Основное препятствие использования GS - их скорость на современном железе. Тормозят. Основная причина - "анти-параллельность" GS, то есть так как шейдер может выдавать variable input и GPU обязана сохранять последовательность вывода треугольников, нужно вводить промежуточную стадию, пишушую в память, а потом делать финальный Gather, убивающий дырки.
[править] Stream Out
Это возможность записывать результат работы Vertex Shader/Geometry Shader в память. Например, кешировать обработку геометрии или вообще геометрию, созданную GS. Можно считать итеративные эффекты, типа Cloth/Water. То есть теперь можно напрямую трансформить и записывать геометрию на GPU, не только рисовать пиксели в Render Target. Также есть возможность читать в шейдере из буфера в памяти по индексу, то есть иметь достаточно большую read-only shared memory. NV например предлагает там константы анимации хранить для инстансинга.
[править] Эволюционные изменения в шейдерах
В Shader Model 4 добавлены целочисленные инструкции и битовые операции (можно считать в честном fixed point и передавать булевые флажки), убрано ограничение на количество инструкций (но очень длинный шейдер может упереться в ограничение по времени выполнения пакета на GPU, до 10 сек)
[править] Уменьшение количества draw calls и переключений состояний
Появились массивы текстур, то есть контейнер одинаковых по размеру и формату текстур, из которого шейдер может выбирать по индексу (в DX10.1 - можно и cubemap arrays). Это тот самый atlasing done right - раньше когда в одной текстуре хранили несколько разных, приходилось беспокоиться за мип-левелы, оставлять зазор между текстурами и т. д. Теперь не надо. В шейдер приходят primitive/instance id, в зависимости от instance ID можно использовать другой набор текстур/координат/whatever. Ожидается, что dynamic branch в шейдере быстрый (лучше, чем в DX9-hardware), поэтому можно передавать Material ID и бранчиться по материалам в шейдере. То есть, в теории, можно за один вызов генерировать большое количество геометрии с разными параметрами, текстурами и вообще материалами. На практике, больше всего мешает таки стоимость dynamic branch и проблем, с ним связанных (вычисление градиентов текстурных координат). А остальное - вполне можно и нужно использовать.
[править] Multi-sampling antialiasing features
Небольшая фича, ради одной которой можно переходить на DX10. Теперь в шейдере можно читать каждый MSAA-сэмпл отдельно, то есть писать свой собственный AA-фильтр, вменяемо сэмплить при процессинге и вообще использовать MSAA RT как текстуру. Ещё и AlphaToCoverage вместе с этим теперь официально присутствует. В D3D10.1 это можно делать и с depth textures.
[править] Поддержка depth textures
Теперь depth buffer можно использовать как текстуру. Можно сказать, чтобы при сэмплинге сравнивал со значением и делал фильтрацию соседей, можно достать чистый depth value. Можно даже stencil value достать.
[править] Другие интересные возможности
- есть рендер в volume texture
- в DX10.1 можно скопировать из обычной текстуры нелюды
в compressed на GPU
- есть настоящий conditional render, то есть возможность выкидывать целый draw call по результатам работы GPU асинхронно (можно делать occlusion culling полноценно)
[править] Ссылки
- Александр Будик Для поддержки DX10 видеокарта нужна не всегда?. 3DNews (2 декабря 2008 года). Проверено 2 декабря 2008.
- BlackCat В Windows 7 запуск приложений Direct3D 10/10.1 будет возможен на CPU. IXBT.com (Четверг, 4 декабря 2008 года). Проверено 4 декабря 2008.

