DirectX 12 Multi-engine: asynchronní shadery v praxi
20.11.2015, Pavel Šantrůček, recenze
Co jsou to asynchronní shadery a k čemu vlastně slouží? Jak zapadají do kontextu DirectX 12? Které grafické karty je podporují, které zase ne a proč? V dnešním článku odpovíme právě na takovéto otázky.
Kapitoly článku:
Co jsou to Compute shadery
Compute shader je obecně program (někdy označovaný také jako „Kernel“ nebo „Task“), který je možné alokovat a spustit na výpočetních jednotkách grafické karty a vykonávat tak různé výpočetní operace.
Na tom není nic nového a my tyto výpočetní shadery známe již z předchozích verzí DirectX, kde pomocí nich vznikaly ve hrách různé post-procesingové efekty jako třeba DoF (Depth of Field), Blur, různé druhy anti-aliasingu atd. Možnostem využití Compute shaderů se však meze nekladou a dokonce je možné pomocí těchto výpočetní shaderů vykreslovat objekty přímo do frame bufferu a obcházet tak klasickou pipeline na grafické kartě (rasterizaci).
Doporučujeme naše dřívější články:
- Grafická pipeline: jak se tvoří obraz
- Grafická pipeline: jak se tvoří obraz II
- Grafická pipeline: jak se tvoří obraz III
Výpočetní shadery jsou velkými pomocníky vývojářů her a jejich jediným menším mínusem je nějaký ten čas, který konzumují, než svou práci dokončí. Exekuční doba, kterou shader potřebuje ke své práci, je samozřejmě závislá od jeho komplexnosti. U „běžných“ post-procesingových shaderů se však jedná o dobu velice krátkou v řádu několika milisekund i méně. Problémem ale je, že hra těchto výpočetních shaderů může využívat větší množství a v případě DirectX 11, jehož pipeline je výsostně sériová, se exekuční časy těchto shaderů přičítají ke grafickým operacím a prodlužují tak celkový čas dokončení snímku (latenci).
Příkladem může být renderování snímku na grafické kartě, kdy grafickým příkazům bude trvat vyrenderování snímku napří. 16 ms a následným výpočetním shaderům bude výpočet postprocessingu trvat řekněme 2 ms. Výsledný čas vytvořeného snímku (latence) pak bude dán jejich součtem 16 + 2 = 18 ms.
Nešlo by to ale udělat trochu chytřeji? Proč nespustit grafickou úlohu souběžně s úlohou výpočetní tak, aby se časy exekucí obou úloh nesčítaly, ale překrývaly? Výsledný čas (latence) snímku by pak byl dán dobou exekuce té nejdelší úlohy, časy všech ostatních kratších úloh by byly v tomto čase skryty a nepodílely se tak na prodloužení výsledné latence snímku. Vlastně bychom se tak mohli dostat ve hrách ke grafickým efektům, které by byly naprosto „zdarma“ bez jakéhokoliv dopadu na latenci a snímkovou frekvenci!
Pokud tedy mluvíme o souběžném zpracování vícero úloh na jedné grafické kartě, z nichž jedna je úlohou grafickou, mluvíme tak o tzv. asynchronních shaderech. Abychom pochopili, jak vlastně grafické karty mohou spustit dvě či více úloh souběžně, a co všechno se pro to muselo udělat, musíme jít trochu do historie, tedy k předchůdcům DirectX 12.