Direct3D 10

Матеріал з Вікіпедії — вільної енциклопедії.
Перейти до: навігація, пошук
Логотип DirectX 10

Direct3D 10 (D3D10) — оновлений набір DirectX API (англ. application programming interface) функцій, 10-а версія Direct3D, наступник Direct3D 9. Direct3D 10 надає функції для взаємодії операційної системи і програм з драйверами відеокарти, підтримується апаратно відеокартами класу NV GeForce 8x00, ATI Radeon 2x00 і вище. Ці функції прив'язані до операційної системи в лінійці Windows і доступні в Windows Vista і Windows 7. Windows XP не підтримує DirectX 10 та старші версії. Частково D3D10 працює на відеокартах з підтримкою Direct3D 9.

Офіційна фінальна версія вийшли 10 листопада 2006 року в складі Windows Vista.

Можливості та особливості[ред.ред. код]

Нова модель драйвера[ред.ред. код]

У Windows Vista абсолютно нова модель драйвера — WDDM (Windows Display Driver Model, раніше звана LDDM — Longhorn Display Driver Model) — серйозна зміна в моделі відеодрайвера з часів появи апаратного прискорення. У XDDM (Windows XP Display Driver Model) кожен виклик DirectX додавав покажчик команди (токен) в буфер команд у незалежному від відеокарти форматі. Коли DX Runtime вирішував, що буфер досить заповнений, викликалася функція драйвера (в режимі ядра), яка отримувала цей буфер. Після цього драйвер розбирав цей буфер і передавав дані відеокарти. Тобто ніяких функцій драйвера в режимі користувача не було. Розвиток відеокарт і, як наслідок, ускладнення буфера команд призвело до того, що драйвер став немислимо великим і у випадку будь-якої помилки провокував BSOD. Також у XDDM у операційної системи немає способів встановлення пріоритету, управління відеопам'яттю, планування викликів DX, що ускладнює поділ відеокарти між декількома процесами — причина «втрати пристрою».

У новій моделі драйвера зроблено поділ між користувальницької і працюючої у режимі ядра частиною драйвера. Всі виклики DX безпосередньо йдуть в користувальницький драйвер, який готує відразу буфер з вмістом, залежних від устаткування. Цей буфер передає дані в ядро ​​операційної системи, звідки вони йдуть на відеокарту. Таким чином вся важка робота виконується в користувача частини, а в ядрі — пересилання зібраного буфера в DMA-трансфер відеокарти. Як підсумок, якщо користувальницький драйвер впаде, нічого страшного не трапиться — закриється конкретна програма (але не BSOD). І у драйвера більше контролю (коли і скільки викликів функцій ядра робити). Також DX Runtime стає зовсім тонкий — немає буферів команд, безпосередньо викликаються функції драйвера. Крім цього між призначеними для користувача і ядерними частинами є планувальник завдань, який обирає які зібрані буфери відправляти відеокарті (поділ GPU на багато процесів).

Віртуалізація відеопам'яті[ред.ред. код]

Тепер якщо не вистачає відеопам'яті, то ресурси переносяться в системну (звідки можуть бути відсвоплені). За рахунок наявності у Windows Vista контролю виділення відеопам'яті (раніше, у драйвера) можна розподіляти її більш ефективно, ніж POOL_MANAGED в XDDM. На даному етапі це працює на програмному рівні — планувальник GPU перед передачею DMA-пакета мапі завантажує всі потрібні текстури у відеопам'ять (вміє довантажувати їх заздалегідь, поки GPU зайнятий іншим і вільна шина). Якщо програма повноекранна, все зайве з відеопам'яті буде перенесено в системну пам'ять в міру необхідності; якщо у віконному режимі, то відбувається розподіл пам'яті між поточними процесами. Якщо потрібно гарантувати 100% наявність ресурсу в відеопам'яті, то необхідно використовувати повноекранний режим і контроль над розміром виділень.

Відсутність ситуації «втрати пристрою» (Device Lost)[ред.ред. код]

У попередніх версіях з різних причин міг відбуватися Device Lost, після чого було потрібно завантажувати всі ресурси у відеопам'ять заново і робити відновлення об'єктів. З новою моделлю драйвера цієї проблеми більше не існує. Можлива ситуація Device Removed, яка означає, що відеокарта була фізично видалена з системи або що відеодрайвер був оновлений. Ситуація зустрічається дуже рідко.

Прибрані списки можливостей (D3D caps)[ред.ред. код]

У DX10 більше немає капсів, як таких. Гарантується наявність всієї функціональності, тобто якщо карта підтримує DX10, то вона зобов'язана підтримувати останню версію шейдерів в повному обсязі, підтримувати всі формати текстур, всі можливі режими фільтрації, шаблону (stencil) і всього іншого. Більше того, для DX10 написали специфікацію правил растеризації, тобто тепер картинка на різних відеокартах на однаковому коді завжди повинна бути однаковою і збігатися з еталонним програмним растерізатором. Якщо це не так, то це баг виробника відеокарти. Надалі функціональність буде розширюватися (пакет DX10.1, DX11 і т. д.).

Зменшено час виклику функцій DirectX[ред.ред. код]

Зменшено час виклику функцій (в тому числі DIP) на CPU. За даними презентацій Microsoft можна спостерігати 10x зменшення часу. Це суттєво, тому що важка гра може проводити близько 10 + мілісекунд у викликах DX. Велику частину часу виклику раніше йшло на Runtime і Driver. тепер driver model фактично нічого не робить, а відразу надає виконання драйверу.

Об'єкти стану (State Objects) і Constant Buffers[ред.ред. код]

З'явилися State Objects — об'єкти, які можна заздалегідь зібрати при створенні і потім швидко встановлювати на відеокарті. Додані Constant Buffers, що дозволяють більш ефективно виставляти константи шейдерів.

Використання об'єктів стану[ред.ред. код]

Всі 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.

Буфери і біндінг[ред.ред. код]

Для основних типів даних (вершин, індексів, констант) запроваджено єдиний буфер — ID3D10Buffer — набір байтів в пам'яті. Type safe забезпечується за рахунок вказівки при створенні вмісту буфера. Для ресурсів введені окремі об'єкти для біндінга до конвеєра — resource views. Тобто спочатку створюємо текстуру як об'єкт в пам'яті, а потім її resource view як інпут для шейдера або як render target, і вже з цим view викликаємо PSSetShaderResources (замість SetTexture) і OMSetRenderTargets (замість SetRenderTarget). Варто відзначити, що в одного ресурсу може бути кілька resource views.

Такий принцип дозволяє працювати узагальнено. Існують «безтипні» (typeless) ресурси, тобто ресурси, які не мають певного типу (не зазначений при створенні) — наприклад, DXGI_FORMAT_R32G32B32_TYPELESS. Тип таких ресурсів визначається під час створення view (наприклад, DXGI_FORMAT_R32G32B32_UINT або DXGI_FORMAT_R32G32B32_FLOAT) і вибору елемента / Слайса з масиву текстур / об'ємної текстури.

Використання буферів констант[ред.ред. код]

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 додали атрибути для хінтів компілятору — розмотування циклів і вибір dynamic vs static branching для умовних переходів.

Еволюційні зміни в шейдерах[ред.ред. код]

У Shader Model 4 додані цілочисельні інструкції і бітові операції (можна вважати в чесному fixed point і передавати булеві прапорці), прибрано обмеження на кількість інструкцій (але дуже довгий шейдер може впертися в обмеження за часом виконання пакету на GPU, до 10 сек)

Геометричні шейдери (Geometry Shader)[ред.ред. код]

Геометричний шейдер — додатковий шейдер між вершинним (Vertex Shader) і піксельним (Pixel Shader), який може генерувати примітиви. На вхід йому подається примітив з інформацією про сусідів, на вихід — можна згенерувати кілька (не фіксоване число).

Stream Out[ред.ред. код]

Це можливість записувати результат роботи Vertex Shader / Geometry Shader в пам'ять. Наприклад, кешувати обробку геометрії або взагалі геометрію, створену GS. Можна вважати ітеративні ефекти, типу Cloth / Water. Тобто тепер можна напряму трансформувати і записувати геометрію на GPU, не тільки малювати пікселі в Render Target. Також є можливість читати в шейдері з буфера в пам'яті за індексом, тобто мати достатньо велику read-only shared memory. NV наприклад пропонує там константи анімації зберігати для інстансінга.

Зменшення кількості 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 можна скопіювати зі звичайної текстури в стислу на GPU
  • є справжній conditional render, тобто можливість викидати цілий draw call за результатами роботи GPU асинхронно (можна робити occlusion culling повноцінно)

Додаткові факти[ред.ред. код]

Операційна система Windows XP не підтримує DX10. Причина в тому, що перенесення нової драйверної моделі неможливе — потрібно занадто багато змін в ядрі операційної системи. Якщо ж переносити тільки набір нових функціональних можливостей DX10, то теж виникають проблеми: віртуалізацію і шедулінг неможливо здійснити в старій моделі драйвера, перенесення апаратних можливостей — занадто великий обсяг роботи для Microsoft і IHV.

Див. також[ред.ред. код]

Посилання[ред.ред. код]

Інформація і ресурси для розробників[ред.ред. код]