Direct3D 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.
Див. також
- GDI
- OpenGL
- Simple DirectMedia Layer
- X (DirectX) — формат файла для зберігання 3D об'єктів, розроблений Microsoft для DirectX
Посилання
- Direct3D 10 Graphics
- Перелік ігор, що підтримують DirectX 10
- Александр Корень (16 лютого 2007 року). DirectX 10 – десятый шаг навстречу виртуальному миру. еженедельник «Компьютерное Обозрение». Архів оригіналу за 17 березня 2012. Процитовано 2 серпня 2009.
- Александр Будик (2 грудня 2008 року). Для поддержки DX10 видеокарта нужна не всегда?. 3DNews. Процитовано 2 грудня 2008.
- BlackCat (4 грудня 2008 року). В Windows 7 запуск приложений Direct3D 10/10.1 будет возможен на CPU. IXBT.com. Архів оригіналу за 17 березня 2012. Процитовано 4 грудня 2008.
Інформація і ресурси для розробників
- Gamedev.net's DirectX Articles section
- DirectX World — C++ DirectX 9 lessons for game programming. Learn how to build a graphic engine.
- Direct3D.net — Сайт Wolfgang Engel'а (Direct3D)
- Drunken Hyena — уроки, код, утиліти, ігри
- Andy Pike's DirectX8 Tutorials — охоплює 2D, 3D, звук, музику, введення
- CodeSampler.com — Приклади та уроки використання Direct3D в програмуванні ігор на C++ і C#
- Managed Direct3D — Direct3D, уроки на С#, Craig Andera.
- NeXe — Архів уроків NeXe (Direct3D 8), archive.org
- Managed Direct3D — Direct3D, уроки на С#, Pieter Germishuys
- Clootie graphics pages — Clootie graphics pages
- DirectX 10 WV — Нова версія DirectX 10 для Windows XP (рос.)
- GameDev.ru — російськомовний сайт розробників 3D програм.