Vélemény: mi áll a DirectX lassú fejlődésének hátterében?

Nem fejlődik elég gyorsan a DirectX?

A PC-s játékosok közül mindenki ismerheti a Microsoft grafikus API-ját, ami a DirectX (technikailag Direct3D) névre hallgat. Az elmúlt hetekben azonban elég sok vád érte ezt a rendszert, ami főleg a Mantle miatt alakult ki. Az AMD API-járól már írtunk egy cikket, így ezzel most nem is szeretnénk foglalkozni, de azt mindenképp érdemes megnézni, hogy a DirectX fejlesztése mégis hol és miért csúszik el, hiszen annyi biztos, hogy egy API nem működik jól, ha a PC-s fejlesztők egy gyártóhoz rohannak megoldásért.

Mindenekelőtt meg kell jegyezni, hogy teljesen más egy szabványos grafikus API-t tervezni, és csupán a fejlesztői igények alapján összeállítani egy alacsony szintű API-t, aminél csak egy architektúra működését vették figyelembe. Nem is ez a fejlesztők gondja a DirectX-szel, hiszen absztrakcióra van szükség ahhoz, hogy többféle hardvert kezeljen a rendszer, de egy bizonyos szint után "az adott API túl vastagnak számít", aminek eredménye, hogy nem kevés teljesítmény marad benne.

A Microsoft grafikus API-ja egy ideje már elérte ezt a szintet, míg a kifejezetten drasztikus lépésnek számító Mantle lényegében minden szempontból törekszik minimalizálni a többletterhelést. Ilyet már csak a puszta működése miatt sem szeretne tervezni a Microsoft, mivel kevés fejlesztő szeretne úgy dolgozni, hogy minden egyes GPU-architektúra működését betanulják. Viszont óhatatlanul ott motoszkál bennünk a kérdés, hogy valóban csak ekkora lépésekben lehet haladni, vagy esetleg lehetne találni egy arany középutat is?


A DirectX 10 előrelépése a késleltetés csökkentése szempontjából [+]

Az előbbi bekezdés végére reagálva nyilván van köztes állapot is, ez viszont újabb kérdéseket szül. Többek között fontos lenne tudni, hogy miképp valósítható ez meg, illetve reálisan kivitelezhető-e számos konkurens gyártó támogatása, és ha igen, akkor mért nem csinálta már meg a Microsoft? Remélhetőleg sokan emlékeznek még a DirectX 10-re, ami nagyjából öt éve jelent meg, és egy igen radikális fejlesztésnek számított a történelemben. Akkor még a Microsoft nem zárkózott el a komolyabb előrelépéstől, így számos olyan lehetőség építettek be, ami a korábbi verziókhoz képest jelentősen csökkentette a többletterhelést.

A fejlesztések többsége jól sült el, de öt év elteltével még mindig ugyanezekre az alapokra építünk, így jelenleg ez jelenti a nehézséget, mivel a hardverek sokat fejlődtek, illetve a különböző programok is csak bonyolultabbak lettek. Erről a fejlesztők régóta beszélnek, tehát újdonságról nincs szó, de tulajdonképpen sose beszéltünk arról, hogy az érintettek mégis miért szeretnének egy DirectX-nél fejlettebb API-t. Nyilván nem volt értelme, mivel eddig erre nem volt lehetőség, viszont tényleg érdemes megvizsgálni, hogy miből fakad a gondok forrása valójában.

Hirdetés

Az alapvető gondok a DirectX-szel

A legtöbb, AAA kategóriás PC-s játék fejlesztésével foglalkozó programozó az elsődleges gondnak a DirectX kiszámíthatatlanságát jelöli meg. Ez régen nem volt akkora probléma, de ahogy fejlődik a grafika komplexitása, úgy kell egyre több „csodát tennie” a drivereknek, hogy a program egyáltalán működjön. Ez viszont komoly időveszteség lehet a feldolgozás során, és ami a legszörnyűbb, hogy igazából a programozónak nincs rálátása arra, hogy pontosan mi zajlik a driveren belül, erre optimalizálni pedig ilyen körülmények között elég nehéz. Kicsit olyan a helyzet, mint vakon átvezetni a zebrán egy vak embert. Lépdelnénk előre, de nem tudnánk, hogy a következő lépést hogyan érdemes megtenni. Az alapvető gond a driverekben keletkezik, mivel nincs igazán logikus mód az API parancsait lefordítani a GPU parancsaira.

Az AMD és az NVIDIA egy ideje már azt a koncepciót követi, hogy a GPU parancsait teszik megközelítőleg olyanná, amilyenek az API parancsai. Technikailag ez adja a legjobb teljesítményt, de ezzel is van a legtöbb munka, mivel a jó működéshez minden egyes játékhoz profilt kell alkotni, jól kell paraméterezni hozzá, illetve esetleg olyan speciális rutinokat kell fejleszteni, amit más játékban nem lehet használni. A driver azonban nem tesz csodákat, még ha úgy is tűnik. Igazából csak annyi történik, hogy egy alapvetően logikátlan működésből próbálja a lehető legtöbbet kihozni, és ez bizony mellékhatásokat is magával hoz. Többek között a mai grafikus meghajtók általános optimalizálásának számít a rajzolási parancsok agresszív pufferelése. Manapság mindegyik cég ilyen elvű működést alkalmaz az eszközillesztőkben, ami növeli az elérhető sebességet, de ezzel párhuzamosan növeli a késleltetést is. Ez persze sokszor nem lényeges, de esetenként okozhat kellemetlen szituációkat, főleg majd a virtuális valóságra vonatkozó hardverek érkezésével.

És az igazi gondok felsorolását még csak most kezdjük. Az egyik legnagyobb problémája a fejlesztőknek, hogy a DirectX-ben a feldolgozáshoz szükséges erőforrások létrehozása sokszor igen sokáig tart, és ez szintén egy megjósolhatatlan folyamat. Ezt még tetézi, hogy a létrehozott erőforrások memóriamenedzsmentje felett nincs direkt kontrollja a futtatott programnak, ami végtére is oda vezet, hogy a programok VRAM-igénye magasabb lesz annál, ami igazából reális lenne.

Ezt egyszerű példával nehéz szemléltetni, de elmondható, hogy a Microsoft API-jában minden erőforráshoz rendelhető egy memóriaterület, ami tulajdonképpen egy textúra lesz egyénileg megadott, de későbbiekben megváltoztathatatlan tulajdonságokkal. A driver a memória méretét az igényeknek megfelelően meghatározza és hozzárendeli az erőforráshoz.

Nyilván az erőforrásokat nem véletlenül hozzák létre a fejlesztők, így ezeket fel is használják, viszont a teljes képszámításnak csak egy nagyon kis részletét kell például egy render targetbe kimenteni. Ha ez megvan, akkor az erőforrás lényegében csak teherré válik, mert tovább nincs rá szükség. Viszont a megsemmisítése igen időigényes a DirectX-en belül, így inkább otthagyják a memóriában. Pedig igazából újra lehetne hasznosítani, hiszen a képszámítás további részében biztos lesz más render target is, ami beleírható a már nem használt memóriaterületbe. Ez sokkal logikusabb működés lenne a mai modern hardverek mellett, és igazából minden ma elérhető integrált és dedikált grafikus vezérlő támogatná.


A DirectX kiszámíthatatlanságának alapjai a Nixxes tálalásában [+]

A fentiek mellett a fejlesztők még a valós idejű shader fordítástól is rettegnek, mivel meghatározhatatlan, hogy ez mennyi időbe kerül. Maga a DirectX API a magas szintű HLSL kódot Direct3D shader assembly nyelvre fordítja, ami tulajdonképpen felfogható a gyártók által egységesen támogatott virtuális utasításarchitektúrának. Ebből a driver a hardver számára is értelmezhető kódot kreál, de csak akkor, ha az adott pálya betöltődik, vagy rosszabb esetben a játék közben, ténylegesen valós időben. Ráadásul figyelni kell arra, hogy a pályák betöltése ne tartson sokáig, vagyis a drivereknek nincs túl sok idejük agresszív optimalizációra. Ezt el lehetne kerülni előre lefordított shaderekkel, amelyeket az adott hardverhez lehetne igazítani. Mindezt persze könnyebb mondani, mint megvalósítani, de alternatívákat be lehetne építeni a szabványos API-ba. Ugyanakkor ezt az irányt a gyártóknak is segítenie kellene a megfelelő fordítókkal.

Az új rendszerrel azonban egy másik jelentős probléma is megszűnne: amikor a drivernek valós időben kell kijavítania az egyes kódrészleteket, hogy az igazodjon az adott hardver működéséhez. Ez sajnos nem egyszerű folyamat, és megfelelő optimalizálás nélkül a javítás úgynevezett mikroakadást is okozhat, mert előfordulhat, hogy sok időt vesz igénybe. Szintén problémásak a tartalom folyamatos streamelésére építő motorok, ezek ugyanis menet közben töltik be a memóriába a szükséges adatokat és sajnos a shadereket is, amelyeket menet közben kell lefordítani. Ez szintén mikroakadáshoz vezethet a hirtelen megnövő processzorhasználat miatt, illetve a textúrák betöltése is késhet, ami szintén nem kedvező.

Mit lehet tenni a DirectX-ért?

Az előbbi oldalon tárgyaltak alapvetően szoftveres korrekciók, tehát nincs igazából lényeges követelményük a hardverre vonatkozóan. Ugyanakkor nem lehet elmenni amellett szó nélkül, hogy a mai modern grafikus processzorok már sok helyen teljesen másképp működnek, mint a DirectX API. Többek között az AMD GCN és az NVIDIA Kepler architektúrája támogatja a bindless modellt, ugyanakkor a szabványos API-k ezt képtelenek kihasználni. Ez nem kis probléma, mivel a DirectX úgy tekint a GPU-kra, mint egy CPU-nak kiszolgáltatott buta szolgára, holott a mai grafikus vezérlők már annyit tudnak, mint egy központi processzor.

A Microsoft API-ja a működést tekintve számos slotot biztosít a fejlesztőknek, amelyek logikailag a virtuális utasításarchitektúra regisztereinek foghatók fel. Amikor a program beköt egy slotot, akkor a driver rengeteg munka elé néz, ugyanis a textúraadatokat olyan adatstruktúrába rendezi, amit a hardver megért. Ez kifejezetten sok erőforrást igényel a processzortól, pedig a modern GPU-kon erre nem lenne szükség. A bindless modellel ugyanis a grafikus vezérlő egy pointert kap, amit követve megtalálja a szükséges textúrainformációt. Persze ehhez tényleg AMD GCN és az NVIDIA Kepler architektúrájú hardver kell, de írható lenne egy olyan DirectX 11.1-es kiterjesztés, ami enyhe korlátozások mellett ugyan, de kihasználná az említett két rendszer működését. Nem is igazán értjük, hogy ezt a Microsoft miért nem lépte meg eddig.

Az occlusion query technikán is lehetne javítani. Mint ismeretes, ez az eljárás jelzi, hogy melyik objektum van más objektum által takarásban a feldolgozandó képen. Amennyiben az eltakart objektum nem látszik, felesleges erőforrást pazarolni rá, így azt a rendszer kivágja még a leképzés megkezdése előtt. Az előzetes leképzést megoldja a grafikus processzor, de az így generált adatokat csak a központi processzor képes olvasni. A DirectX-ben tehát a GPU által kreált eredményt vissza kell másolni a CPU-nak, amely eldönti, hogy mit kell kirajzolni és mit nem, de az adatok másolása önmagában több időt vesz igénybe, mintha a processzor egy szoftveres futószalaggal átvenné az előzetes leképzés munkáját, és úgy értékelné ki a végső képkocka szempontjából fontos objektumokat. Viszont a kiértékelést el tudnák végezni a modernebb GPU-k, tehát egy fejlettebb API-val nem kellene a processzornak visszaírni semmit, hiszen minden helyben eldőlne a grafikus vezérlőn belül.

Szintén javítható lenne a DirectX 11-ben bevezetett deferred context funkció, ami megpróbálta a rajzolási parancsok többszálú feldolgozását megoldani. Ez nem sikerült túl jól, hiszen máig egyetlen ember volt képes hatékony implementációt készíteni, és ő is elégedetlen volt a rendszer működésével. De annak igazából nincs sok akadálya, hogy az egyes szálakon parancspuffereket kreáljon a rendszer, amit a parancslistákba betöltve rá lehet engedni a hardverre. Ráadásul ezek a parancspufferek újrahasznosíthatók is lehetnének. Önmagában ez tisztán szoftveres kérdés. Persze a Microsoft újra felrúgná a DirectX visszafelé kompatibilitását, ahogy azt tették a DirectX 10 esetében, de legalább hatékonyabb lenne a rendszer.


Az aszinkron feldolgozás előnyei a Nixxes szerint [+]

Végül megjegyezzük, hogy nagyon hasznos lenne, ha a szabvány API-k aszinkron feldolgozást is támogatnának. Ehhez persze tényleg modern hardver kell, mint az AMD GCN architektúrája, illetve az NVIDIA Kepler megoldásai közül a GK110-es és a GK208-as GPU. Ezekkel megoldható az, hogy a grafikus API egymás mellett adjon át grafikus és compute parancsokat a GPU-nak. A DirectX-ben ez nem ilyen egyszerű, mivel az API csak szinkronizált munkafolyamatot tölt be a parancslistába. Persze vannak tipikus szituációk, amelyekre a drivereket ki lehet gyúrni, így a háromszögek rajzolása valamennyire átlapolható az általános számításokkal, de ez csak tűzoltásra jó.

Sajnos tipikus eset a mai játékokban, hogy az árnyéktérképek leképzése mellett a grafikus vezérlők számítási kapacitása kihasználatlan. Aszinkron ütemezéssel azonban az előbbi számítás mellé be lehet tölteni olyan szimulációs feladatokat, mint a TressFX. A két számítás külön hardverelemeket terhel, tehát jól elvannak egymás mellett. Ennek hála tulajdonképpen mondhatjuk azt is, hogy a TressFX szimulációja kvázi ingyenessé vált. Persze ez csak egy példa, számos más szituációt el lehet képzelni, de mindenképp fejleszteni kell az API-n.

Véleményünk szerint a Microsoft túl lassan halad a DirectX fejlesztésével, ami az előbbiek mellett tisztán látszik. Persze az is világos, hogy ha nem ragaszkodnánk a visszafelé kompatibilitáshoz, akkor igazából számos területen előrébb tartana a DirectX, és az újítások nagy többsége az aktuális hardvereken is kihasználható lenne, de az AMD GCN és az NVIDIA Kepler architektúrájával biztos. Márpedig a hardcore játékosoknak igazából ez számít. Mindez csak elmélet, de a színfalak mögött biztosan nincs minden rendben, különben számos vezető fejlesztő nem rohanna egy gyártóhoz segítségért.

Ez igazából senkinek sem előnyös, még magának a piacnak sem, de önmagában többet ártana a PC-nek, ha a két új generációs konzol grafikában elhúzna a jóval drágább konfigurációktól. Vajon a Microsoft erre pályázik az Xbox One-nal? Vagy egyszerűen csak arról van szó, hogy a gyártók nem tudnak igazán megegyezni a jövőben követendő irányról? Nehéz lenne ezeket a kérdéseket megválaszolni, de úgy gondoljuk, hogy a Microsoftnak erélyesebben kellene fellépni az újítások bevezetésével, még akkor is, ha nem mindenkinek ugyanaz a jövőképe. Mivel az utolsó szó a Microsofté, így amennyiben egy új funkció nagy előnyt jelentene, akkor azt igenis írják elő, és aki komolyan gondolja a PC-s játékpiacot, az úgyis támogatni fogja.

Abu85

Azóta történt

Előzmények