Kyro II: David proti Goliáši

Grafické čipy se za posledních 10 let téměř vůbec nezměnily. Větší rychlosti vykreslování trojrozměrné scény bylo dosaženo především využitím paralelismu (zpracování více instrukcí najednou) a zvýšením pracovní frekvence jak samotného čipu, tak paměti - tedy hrubou silou. Proti síle lze však postavit chytrost a v roli Davida se tak ocitá grafický čip Kyro, z papírového hlediska zanedbatelný drobek, který si však může troufnout i na GeForce 2. Tajemstvím jeho úspěchu je tzv. tiling...
Kapitoly článku

I když se tvrzení o nepatrných změnách grafických čipů za posledních 10 let může zdát nadsazené, z hlediska postupu zobrazení trojrozměrné scény je pravdivé. Tento postup vychází z grafického systému počítačů Silicon Graphics a v různých obměnách jej obsahují téměř všechny grafické čipy, které můžete najít v grafických kartách (99%). Jedinou výjimkou je rodina grafických čipů PowerVR, kam patří také Kyro. Abychom se mohli blíže podívat na podstatu jeho odlišnosti a z toho plynoucích vlastností, je třeba alespoň stručně přiblížit základy zobrazení trojrozměrné scény, tentokrát bez matematiky.

Vše začíná světem, ve kterém je umístěn pozorovatel. Světem může být např. úroveň počítačové hry (Quake), pozorovatelem pak postava, kterou ovládáte, a jejíž zrakové vjemy vidíte na obrazovce monitoru. Pozorovatel vidí pouze část světa, tzv. scénu. Scéna se skládá z různých objektů (např. stěny, předměty, postavy), které jsou popsány svým povrchem. Např. krychle se skládá ze 6 stěn (viz obrázek). Grafické čipy však pracují s trojúhelníky (nejjednodušší rovinný útvar, jeho použití výrazně zjednodušuje výpočty spojené se zobrazením scény), takže každou stěnu je třeba popsat jejich dvojicí. Krychli tak grafický čip pokládá za objekt, jehož povrch je tvořen 12 trojúhelníky (viz obrázek). Stejným způsobem jsou popsány téměř všechny objekty scény.

Zná-li polohu (kde se nachází) a orientaci (kam se dívá) pozorovatele, vybere aplikace objekty, které mohou být viditelné - scénu. Při jejím zobrazení je třeba především vyřešit viditelnost, tedy jaké části jakých objektů budou viditelné (např. jedna postava bude viditelná pouze z části, protože stojí za oknem, druhá postava nebude vidět vůbec, protože je schovaná za stěnou). Grafický čip tak postupně dostane spoustu trojúhelníků, které má správně zobrazit.

Tradiční architektura

Viditelnost je řešena převážně pomocí z-bufferu - pomocné paměti, která obsahuje vzdálenost dosud nejblíže vykresleného pixelu (viz obrázek). Jak vlastně pracuje? Z-buffer má stejné rozlišení jako frame-buffer (paměť, kam je postupně vykreslována scéna, jeho konečnou podobu vidíte na obrazovce monitoru). Frame-buffer je vyplněn zvolenou barvou (v našem případě bílou) a do všech prvků z-bufferu je zapsána hodnota nekonečno, což znamená, že příslušný pixel ještě nebyl ani jednou vykreslen. Nyní přijde na řadu první trojúhelník. Grafický čip jej rozloží na pixely, které postupně zpracovává. U každého z nich určí především barvu (ovlivněno materiálem, texturou, osvětlením) a tzv. z-hodnotu - vzdálenost od obrazovky (nebo méně přesně řečeno - pozorovatele). Zvolil jsem jednoduchý příklad, takže všechny z-hodnoty jsou stejné.

Nyní přichází tzv. z-test, kdy je získaná z-hodnota porovnána s hodnotou uloženou v z-bufferu. Pokud je získaná z-hodnota menší, znamená to, že pixel je blíže než nejbližší dosud vykreslený (tedy je viditelný) a můžeme jej zobrazit (zapsat barvu do frame-bufferu a z-hodnotu do z-bufferu). V opačném případě je dál než nejbližší dosud vykreslený pixel (tedy není viditelný) a je zamítnut - není vykreslen. Stejným způsobem jsou zpracovány všechny další trojúhelníky a výsledkem je korektně zobrazená scéna (na obrázku vidíte, že při vykreslování druhého trojúhelníku byla sice pro část pixelů určena barva, ta však nakonec nebyla použita, neboť z-test byl neúspěšný). Celý postup je pochopitelně mnohem komplikovanější (průhledné trojúhelníky je třeba zpracovat až na konec, je třeba řešit rovnost při z-testu), účelu našeho článku však v této podobě vyhovuje.

Problém je v nefektivitě

Určitě jste již často narazili na skutečnost, že s vyšším rozlišením klesá počet vykreslených snímků (obrázků) za sekundu, a hra se začíná citelně "trhat". Obvyklé vysvětlení spočívá v tvrzení, že grafický čip má více práce, neboť musí vykreslit větší množství pixelů. To je sice pravda, současné grafické čipy jsou však tak rychlé, že pro ně není sebemenším problémem ani rozlišení 1600×1200, případně vyšší. Pravou příčinou nedostatečná datová propustnost cesty mezi grafickým čipem a pamětí grafické karty. Ta v současnosti dosahuje až 8 GB/s, grafické čipy ji však s výjimkou rodiny PowerVR využívají velmi neefektivně. Jednu z příčin jsem již zmínil - pro každý pixel každého trojúhelníku je určena barva (v závislosti na počtu textur a druhu filtrování je třeba z paměti načíst patřičný počet bodů textur - texelů) a pro z-test je třeba získat patřičnou hodnotu ze z-bufferu (další přístup do paměti). Pokud pixel neprojde z-testem, je zamítnut a celý proces proběhl zbytečně. Podobně pokud je pixel zapsán do frame-bufferu a později je přepsán jiným, přišla i v tomto případě vynaložená práce nazmar.

Je zřejmé, že čím více zakrytých pixelů bude scéna obsahovat, tím větší budou nároky na datovou propustnost (která je konstantní) a tím menší bude počet vykreslených snímků za sekundu. Zajímavým údajem je tzv. míra překreslení (overdraw), která udává, kolikrát je průměrně vykreslen každý pixel obrazu. U současných her se míra překreslení pohybuje v rozsahu od 2 do 3, čemuž odpovídá i množství zbytečně vynaložené práce. Navíc se jedná o hodnoty průměrné, což znamená, že krátkodobě mohou být mnohem vyšší. Výsledkem je pak nepříjemný chvilkový propad rychlosti vykreslování.

To však zdaleka není konec všech problémů. Další nastane ve chvíli, kdy je trojúhelník pokryt více texturami, než kolik je grafický čip schopen najednou zvládnout (většinou 2 až 3). Uvážíme-li jednoduchý případ, kdy je trojúhelník pokryt 3 texturami a grafický čip umí najednou pracovat pouze se 2 (obvyklá situace), bude vykreslování probíhat následovně: Nejdříve budou pro určení barvy pixelu použity první 2 textury a výsledek bude zapsán do paměti - frame-bufferu. Poté bude určena barva pixelu na základě třetí textury, z paměti bude načtena dosud vypočtená hodnota a výsledek, který vznikne jejich sloučením, je opět zapsán do paměti. Je tu tedy potřeba dalšího přístupu do paměti, který bude znát v případě, kdy barva bude určena zbytečně (pixel neprojde z-testem nebo bude později překryt jiným). Nepříjemný je také vznik zaokrouhlovacích chyb při zápisu do frame-bufferu. Grafický čip totiž může pracovat s větší barevnou přesností (např. 32bitovou) než je barevná přesnost - hloubka frame-bufferu (např. 16bitová). V tomto případě dojde k chybě už při prvním zápise, kdy je nutno 32bitovou hodnotu uložit jako 16bitovou prostřednictvím procesu zvaného dithering. Vrátíme-li se tedy k případu trojúhelníku pokrytého 3 texturami a grafickému čipu, který umí pracovat se 2 texturami najednou, jsou již data načtená z frame-bufferu při nanášení třetí textury zatížena chybou a tato chyba se dále zvětšuje opětovným zápisem výsledné barvy.

Témata článku: , , , , , , , , , , , , , , , , , , , , , , , ,