2010. március 8., hétfő

Direct2D - Ismertető

Egy havi kihagyás után újra belevetettem magam a fejlesztésbe - máshoz úgyse nagyon értek - közbe pedig megjelent néhány olyan új technológia, amely felkeltette az érdeklődésemet. Erről adnék most itt egy rövidke kis áttekintést. Tehát most a Windows-on elérhető 2D-s prezentációs technológiák összehasonlításáról lesz szó. Windowson jelen pillanatban elérhető három darab 2D-s prezentációs technológia:
  • GDI (Graphics Device Interface)
Az alkalmazások javarésze (beleértve a MS alkalmazásokat), még ma is ezt használja. Az igazság az, hogy a GDI alapvető hiányosságoktól szenved. Nem támogat magas minőségű rajzolást. Nincs támogatás élsimításhoz (anti-aliasing), aminek köszönhetően a ferde vonalak csipkézettnek tűnnek. Mi több, nincs teljes támogatás áttetszőség (transparency) kezeléshez, úgy mint támogatása a félig áttetsző (semi-transparent) ecseteknek (brushes) és tollaknak (pens).
A GDI-t nem párhuzamos feldolgozáshoz tervezték és emiatt egy kevésbé hatékony lokkolási mechanizmustól szenved. A Windows 7-ben és Windows Server 2008 R2-ben újratervezték ezt a lokkolási mechanizmust, hogy legyen sokkal kifinomultabb, szemcsésebb, de a teszteredmények azt igazolják, hogy az új Direct2D még mindig jobban skálázódik.
Egy másik probléma, hogy a GDI handle-k totális száma limitált 10240/process és 65536/session-re, mert belsőleg a Windows egy 16 bites egész számot használ, hogy tárolja az indexeit ezeknek minden egyes session-höz. A stock objektumok kikerültek a limitációból. Az egyetlen út áthidalni ezt a limitet egy új session beiktatása, de ez növeli a memória használatot.
  • GDI+ (Graphics Device Interface Plus)
A fő probléma a GDI+-al szerver oldali forgatókönyveknél az, hogy nincs hivatalos támogatás futtatni Session 0 izolációs szinten. Ez annyit tesz, hogy függvények, amelyek próbálnak kapcsolatot teremteni a megjelenítő eszközzel, hibákat fognak kapni, mert nem engedettek Session 0 izolációban. Egyéb függvények is elbukhatnak, mert még ha nem is tűnik úgy, hogy a függvény kapcsolódik a megjelenítő eszközhöz, használhatna valamilyen kerülő utat, ami tiltott.
Máskülönben a GDI+ támogatja az anti-aliasing-et és alpha-blending-et egyaránt, tehát minőségbeli problémái nincsenek mint a GDI-nek, viszont vannak teljesítménybeli problémái továbbra is a lokkolási mechanizmus miatt, és ez az új Windowsokban (Windows 7, Windows Server 2008 S2) sem lett tovább fejlesztve.
  • Direct2D
A Direct2D a Windows 7 részeként megjelenő új 2D-s prezentációs technológia, részben az elavult GDI/GDI+ leváltására. Nemrégiben portolásra került Windows Vista alá is, így a Windows Vista Platform Update keretében mindenki gépére felkerülhetett. Sajnos hozzá kell tegyem, hogy Windows XP-re nem nagyon várható ez a technológia, ugyanis a Direct3D 10 tetejére épül, ami pedig erősen támaszkodik a Vista óta bevezetett új driver modellre, ennélfogva nem valósítható meg az XP-re történő visszaportolás. Megjegyezném, hogy az új Internet Explorer 9 is a Direct2D-t fogja használni weboldalak megjelenítéséhez, használva a GPU erejét az oldalak rendereléséhez.
Technikailag a D2D többszálúság (multi-threading) és Session 0 tudatában lett tervezve az elejétől fogva. A legtöbb többszálazott esetben a D2D lehet szabadon lokkolható használva több egyszálú factory-t, egyet minden egyes szálhoz. Egy factory széles lokkolás mindenképp lesz, ha az adott programnak használnia kell a többszálú módját a factorynak, de ez sokkal szemcsésebb, kifinomultabb, mint a GDI és GDI+ esetében. A hatása a lokkolásnak elhanyagolható és nem exponenciálisan növekszik a szálak számával.

A GDI összehasonlítása a Direct2D-vel

Még mielőtt kitérnék a címben szereplő témára, erősen érzékelhető a neten utánaolvasgatva, hogy eléggé ketté osztja a társadalmat ez a technológia. Egy Direct3D-s játékfejlesztő, akinek a kisujjában van az egész D3D, nevet egyet és azt mondja, hogy én megcsináltam ugyanazt a demot Direct3D-vel 500 sorba, amit a Microsoft Direct2D-vel 800 sorba. Természetesen ez minden további nélkül lehetséges, hiszen a D3D nem zárja ki, hogy 2D-ben programozzunk, sőt mivel a D2D a D3D tetején csücsül, ez fordítva is igaz. De mindazonáltal fontos megemlíteni, hogy a D3D-n túlmenően a D2D garantálja az interoperabilitást a GDI-vel is. Tehát ez nem igazán D3D fejlesztőknek kitalált technológia, hanem sokkal inkább a GDI/GDI+ fejlesztőket próbálják kimozdítani abból az árokból, amibe már hosszú évek óta bele vannak kényszerítve. Ennélfogva ezzel a cikkel csak bizonyos mértékig tudok egyetérteni. Abban teljesen igaza van az írónak, hogy bizonyos szinten feleslegesen túl lett komplikálva, illetve ugyanazokat a konvenciókat követi, mint a D3D, pl. rendering_2d(), ami valóban zavarba ejtő lehet egy GDI/GDI+ fejlesztőnek elsőre, de ez valójában a GDI koncepcionális megvalósítása körül volt igazából elszúrva. Nincs mese, néhány dolgot újra kell tanulni, értelmezni, de annyira nem vészes.

A GDI és a Direct2D is azonnali módú 2D-s renderelő API és mindkettő ajánl bizonyos fokú hardveres gyorsítást. Ez okoz némi zavart - ugyanis akkor miben különböznek ezek egymástól? Miben hasonlítanak egymáshoz? A Direct2D teszi a GDI-t gyorsabbá? Miben különbözik a Direct2D hardveres gyorsítása a GDI hardveres gyorsításától? Ezekre keressük most a választ.

Miben különbözik a Direct2D és GDI-től?

A Direct2D és GDI jobbára a részletekben térnek el, abban ahogy renderelik a képet, ahogy elérik a megjelenítő hardvert, illetve némileg különböznek tervezési elvekben is.
A GDI opaque (átlátszatlan) és aliased geometriákat (paths, lines, stb.) renderel. Továbbá tud renderelni aliased és ClearType szöveget és támogatja a transparency blendinget (áttetszőségi keverést) az AlphaBlend API által. Bárhogy is, az áttetszőség kezelése inkonzisztens. A legtöbb API egyszerűen mellőzi az alfa csatornákat, némelyik pedig használja azt. Talán az egyik legfontosabb dolog, hogy a GDI renderelés nem térképezi fel könnyen, hogy egy modern GPU mit renderel a leghatékonyabban a 3D-s részén a renderelési motornak. Például a ROP-ok (Raster Operations Pipeline) nem lehetnek megvalósítottak a keverési szakászában a GPU-nak. Bárhogy is, az alfa lehet. Egy másik példa, a Direct2D aliased vonalai úgy lettek tervezve, hogy legyenek implementáltak egyszerűen mint két darab háromszög, amik a GPU-ban renderelődnek. A GDI garantálja hogy a Bresenham féle vonal rajzolási algoritmus használt.
A Direct2D opaque (átlátszatlan), transparent (áttetsző), aliased és anti-aliased (élsimított) primitíveket renderel. Szigorúan garantálja az elfogadását és renderelését áttetsző tartalmaknak. Lehetővé teszi tervezni modern felhasználó felületeket, illetve enged renderelni minden primitívet használva hardveres gyorsítást. A Direct2D azonban nem egy tiszta szuperhalmaza a GDI-nek, a primitívek indokolatlanul lassúak volnának ahhoz, hogy implementálva legyenek egy GPU-n, amik nem a Direct2D-ben jelennek meg. Ez az egyik válasz. Tehát a Direct2D nem segít növelni a teljesítményét a GDI-nek, mivel a GDI nem használ Direct2D-t. Ugyanakkor a Direct2D használ(hat) GDI-t (interoperabilitás a régi programokkal).
A Direct2D a Direct3D-t használja, hogy elnyerje a hardveres gyorsítást. A Direct3D egy user modú display driver-t használ, amely becsomagolja a parancsfolyamokat (command streams). A Direct3D leküldi ezeket a parancsfolyamokat és erőforrásokat kernel módba a hardvernek feldolgozásra. Egy nagy előnye ennek az architektúrának, hogy egy alkalmazás tudja használni mind a Direct2D, mint a Direct3D képességeit együtt, hiszen a Direct2D is a Direct3D tetején ül.
A Windows NT 4 óta, a GDI kernel módban fut. Az alkalmazás hív GDI-t, amely aztán hívja a kernel módú hasonmását. Ott, a GDI átpasszolja a primitíveket a saját driver modelljének. Ez a driver aztán elküldi az eredményeket a globális kernel módú display drivernek. Kb. a Windows 2000 óta a GDI és a GDI driverek egy független térben futnak a kernelben, ami "session space"-nek hívott. Egy session címtér létrejön minden bejelentkezett session-höz és mindegyik példányához a GDI-nek, amik futnak függetlenül ebben a különböző kernel módú címtérben.

Mi a különbség a GDI és Direct2D hardveres gyorsítás között?

A legfontosabb különbség, hogy a Direct2D a Direct3D tetejére rétegződik, míg a GDI-nek van egy saját független megfogalmazású driver modellje. Ez a driver modell (GDI Device Driver Interface vagy DDI) megfelel a GDI primitíveknek, míg a Direct3D driver modell megfelel amit a 3D-s hardver a saját grafikus processzorában (GPU) renderel. Amikor a GDI DDI először volt definiált (a 90-es évek elején), a legtöbb megjelenítést gyorsító hardver a GDI primitíveket célozta meg. Idővel, bárhogy is, sokkal de sokkal nagyobb hangsúly helyeződött a 3D-s játék gyorsításra és kevesebb az alkalmazás gyorsításra. Ennek következtében a GDI DDI nem lett implementálva a megjelenítő driverek által, s végül, a BitBlt művelet lett egyedül igazán gyorsított és a legtöbb egyéb művelet nem.

Növekedése a megjelenítő driverek összetettségének és méretének

Időközben a képernyőillesztők egyre összetettebbé váltak, ahogy egyre jobban növekedett a komplexitása a driver 3D-s részének. A magasabb komplexitású kód hajlamos elkövetni több hibát, ezért elvárás volt áthelyezni a driver-t user módba, ahol nem okozhat rendszerújraindulást. Mint ahogy a következő ábrán is látható, a megjelenítő driver ketté-osztott egy komplex user módú komponensre és egy egyszerű kernel módú komponensre:


Nehézség a sessionök és a globális kernel címterek szinkronizálásában

Windows XP-ben egy display driver két különböző címtérben létezik, session space és kernel space. Néhány részének a drivernek szükséges válaszolni plug & play és power menedzsment eseményekre. Ez az állapot szükséges, hogy szinkronizálva legyen a driver állapotával a session címtérben. Ez egy kemény feladat és a megjelenítő driverek hajlamosak hibázni, amikor megpróbálják kezelni ezeket a különböző címtereket.

Az összetett asztal

Az összetett asztalnak szükségelt a GDI, hogy képes legyen renderelni a felületre, amely aztán renderelve lett a Direct3D által a megjelenítőre. Ez nem lehetett könnyedén megvalósítható az XP driver modelljében, mert a GDI-nek és Direct3D-nek párhuzamos driver stack-je volt.
Ennek eredményeként, a Vista-ban a GDI DDI display driver megváltozott és implementálva lett Microsoft szállított driverek által, névlegesen Canonical Display Driver (CDD). A GDI renderelt egy rendszermemória biképre. Az ún. piszkos (dirty) régiók voltak használva frissíteni a videó memória textúrát, amelyet az ablakmenedzser használt, hogy összeállítsa a desktop-ot.

GDI renderelés a Windows 7-ben

A fő hátránya a Windows Vista driver modelljének az, hogy minden GDI ablakot megkellett tartani mind a videó memória felület, mind a rendszermemória felület által. Ezek az eredmények a rendszermemóriában válnak használttá minden nyitott GDI ablakhoz.

Ezen okokból a GDI megváltozott újra a Windows 7-ben, hogy biztosítsa, ne legyen szükség rendszermemória-felületre ablakonként. Mivel a GDI rendereléshez szükséges olvasni, módosítani, írni a rendszer-memória felületet, és mivel a CPU nem tud direktbe hozzáférni a videó-memóriához, a GDI módosítva lett, hogy rendereljen egy részébe a rekesz memóriának. A rekesz-memória lehet frissített a videó-memória felületből megtartva az ablak tartalmakat. A GDI visszatud renderelni a rekesz memóriába, és az eredmény aztán lehet visszaküldött az ablakfelületre. Mivel a rekesz-memória címezhető a GPU által, a GPU tudja gyorsítani ezeket a frissítéseket a videó-memória felületre. Például, a szöveg renderelés, BitBlt közös ROP-al, AlphaBlend, TransparentBlt, StretchBlt, mind gyorsított ebben az esetben. Továbbá, néhány művelet megkerülheti a rekesz-memóriát teljesen, úgy mint BitBlt, ColorFill.

Összehasonlítása a Direct2D és GDI gyorsításnak Windows 7-ben

A Direct2D és a GDI mindketten azonnali módú renderelési API-k, és mindkettőről elmondható (legalábbis részben), hogy hardveresen gyorsított. Akárhogyan is, van számos különbség közöttük.

Helye az erőforrásoknak

A GDI az erőforrásait részleges bitképekben kezeli, rendszer-memóriában alapértelmezésben. A Direct2D az erőforrásait a videó-memóriában, a megjelenítő adapterében kezeli. Ez azt eredményezi, hogy amikor a GDI-nek szükséges frissíteni a videó-memóriát, akkor ezt mindig a fizikai busz felett kell végrehajtani, kivéve ha az erőforrások már történetesen belemásoltak a rekesz-memória szegmensbe, vagy ha a művelet kifejezett lehet direktbe. Egy kivétel itt a bitképek, amelyek a CreateBitmapFromDxSurface API-val vannak létrehozva, amely rezidens a videó-memóriában. A Direct2D viszont egyszerűen átfordítja az ő primitívjeit Direct3D primitívekké, mivel az erőforrások már a videó memóriában vannak.

Metódusa a renderelésnek

A GDI egy nagy részét a renderelésnek a rekesz-memóriába teljesíti, használva a CPU-t. Direct2D-ben van egy translator (fordító), ami átfordítja az ő API hívásait Direct3D primitívekké, az eredmény aztán renderelt a GPU-n. Néhány GDI renderelés is a GPU-n teljesített, amikor a rekesz-memória átmásolt a videó-memória felületre, reprezentálva a GDI ablakot, vagy amikor ez lehetséges.

Méretezhetőség

A Direct2D renderelési hívásai mind független parancsfolyamok a GPU-ba. Minden Direct2D factory reprezentál egy különböző Direct3D eszközt. A GDI egyetlen parancsfolyamot használ minden alkalmazáshoz a rendszerben. A GDI metódusok eredményezhetnek felesleges költséget néhány amortizációjában a GPU és CPU renderelési kontextusnak. A Direct2D megközelítésében kevésbé szükséges a szerializáció a független parancsfolyamok között.

Elhelyezkedés

Természetesen, a Direct2D teljesen user módú, beleértve a Direct3D-t és Direct3D driver-t is. A GDI két módot használ, egy része a session térben van kernel módban, az API felülete pedig user módban.

Hozzáférhetősége a hardveres gyorsításnak

A GDI hardvergyorsított XP-n és Windows 7-en, amikor a DWM fut és amikor a WDDM 1.5 driver használatban van. A Direct2D hardvergyorsított minden körülmény között és bármilyen WDDM driveren, függetlenül attól, hogy a DWM használatban van-e. A Direct2D Vista-ra szintén visszaportolt, ugyanakkor érdemes megjegyezni, hogy a GDI Vista-n mindig a CPU-n fog renderelődni.

Prezentációs modell

Amikor a Windows először tervezve volt, nem volt elég hatékony a memória, hogy minden ablak tárolt legyen az ő bitképében. Ez azt eredményezte, hogy a GDI mindig logikailag direktbe a képernyőre renderelt, változó kivágású régiókat alkalmazván biztosítva azt, hogy ne rendereljen az ablakon kívülre. A Direct2D követ egy modellt, ahol az alkalmazás renderel egy háttér bufferba és az eredmény automatikusan tükrözött ("flipped"), amikor az elkészült a rajzolással. Ez engedi a Direct2D-nek, hogy kezeljen animációs jeleneteket folyékonyabban, mint a GDI (és villogás-mentesen).
Fontos kihangsúlyozni, hogy a GDI ezt a fajta hardveres gyorsítási eljárást csak a Windows 7 óta támogatja. Ugyanakkor érdemes figyelembe venni azt is, hogy a Direct2D XP-n majdnem biztos, hogy nem lesz elérhető. Szóval, aki arra adja a fejét, hogy framework nélküli, cool grafikával ellátott, GPU gyorsított, XP kompatibilis szoftvert készítsen, továbbra is a Direct3D 8/9 a járható út. Ugyanez igaz a játékfejlesztőkre is, mivel viszonylag elég nagy a tesztek alapján az overhead a D3D-hez képest. Viszont akinek adott a lehetőség, hogy Vista/Win7-re fejlesszen natív alkalmazásokat, annak mindenképp érdemes számolnia ezzel és végképp letenni a GDI/GDI+-ról.

Janka János

0 megjegyzés :

Megjegyzés küldése