Nvidia bracht in april 2020 als eerste gpu-fabrikant een eigen temporal upscaler voor games uit voor zijn RTX-videokaarten, in de vorm van DLSS 2.0. Deze opschaaltechniek volgde de eerste versie van DLSS op, die nog een spatial upscaler was. Versie 2.0 kwam bij release beschikbaar voor een aantal games, waaronder Control en Wolfenstein: Youngblood. Twee jaar later is dat aantal behoorlijk uitgebreid; volgens Nvidia zit DLSS in meer dan 150 titels.
DLSS in de pijplijn
DLSS zit, net als veel andere temporal-upscalingtechnieken, relatief vroeg in een renderpipeline. Allereerst vinden de render- en rasterizationstappen plaats. DLSS wordt daarna geplaatst aan het begin van de postprocessingpipeline en vervangt daarmee de antialiasingstap, aangezien DLSS 2.0 upscaling en AA combineert.
De opschaaltechniek van Nvidia heeft verschillende inputs nodig voordat ze kan beginnen met opschalen. Allereerst is er natuurlijk een gerenderde afbeelding op lagere resolutie nodig, die uiteindelijk wordt opgeschaald naar een hogere resolutie. Dat gerenderde frame moet verder aliased en jittered zijn, waarover straks meer. DLSS heeft daarnaast motionvectoren, en informatie over de diepte en exposure van een frame nodig.
Inputs vanuit de engine: gejitterde pixels en motionvectoren
Zoals besproken wordt bij temporal upscaling gebruikgemaakt van informatie uit voorgaande frames. Die extra informatie moet een betere beeldkwaliteit mogelijk maken. Daarvoor moet ieder frame daadwerkelijk nieuwe informatie bevatten en dus iets verschillen van het voorgaande frame, ook als het beeld stilstaat. Om dat te bereiken, zet Nvidia een techniek in die 'pixeljitter' wordt genoemd.
Bij jittering verschuift de renderer héél subtiel de viewport (lees: wat je op je scherm ziet). Die verschuivingen zijn niet zichtbaar in het eindresultaat, maar zorgen er wel voor dat er verschillende samples van een enkele pixel verzameld kunnen worden, zelfs als het beeld 'statisch' is. Nvidia raadt daarvoor een Halton-patroon aan. Dat is een specifieke sequentie waarin de pixels waaruit het beeld is opgebouwd, worden verschoven en die volgens Nvidia erg geschikt is voor het vergaren van informatie over pixels.
Nvidia toonde tijdens de GDC 2021 een voorbeeld van jittering met een flamingo. In de onderstaande gif-afbeelding is te zien hoe de pixels in dit frame subtiel van plaats wisselen.In de praktijk worden de individuele pixels maximaal binnen 0,5 pixel van het midden verplaatst. Door dit te doen, verschuiven ook de randjes van de nek van de flamingo lichtelijk. Dat is extra informatie die door DLSS wordt ingezet om een scherp high-res eindresultaat met antialiasing te leveren op basis van een frame op lagere resolutie en zonder antialiasing.
Bij het renderen van het frame moet ook de mipmap-bias aangepast worden. Dit heeft tot gevolg dat de game individuele textures op een zo hoog mogelijke resolutie inlaadt. DLSS is namelijk alleen bedoeld voor het opschalen van een compleet frame, maar is niet geschikt om de kwalteit van individuele textures te verbeteren, of om low-res textures op te schalen naar textures op een hogere resolutie.
:strip_exif()/i/2005030936.jpeg?f=imagenormal)
De andere primaire inputs bestaan uit motionvectoren. Daarmee wordt beschreven hoe een pixel van frame tot frame over het scherm beweegt. De engine houdt daarmee bijvoorbeeld bij hoe objecten en geometrie over het scherm bewegen, maar ook hoe de viewport beweegt in verhouding tot de 3d-omgeving. Dat levert een vector op die terugwijst naar de vorige locatie van een pixel. De gegevens van die motionvectoren worden bijvoorbeeld gebruikt om de randen van bewegende objecten te corrigeren, om zo ghosting en andere artefacten te beperken.
Opschalen op basis van AI
Op basis van de bovenstaande stappen wordt het inputframe gerenderd op een lagere resolutie, zoals 1080p. Dit frame wordt gevoed aan DLSS en zijn neurale netwerk, de Convoluted Autoencoder genaamd. Dit onderdeel van de pijplijn neemt het daadwerkelijke opschalen op zich, bijvoorbeeld naar 4k.
Nvidia heeft zijn AI-netwerk zelf specifiek getraind op zijn DGX-supercomputers voor het opschalen van afbeeldingen. Tijdens dat trainingsproces wordt een afbeelding in 1080p zonder antialiasing gerenderd en gecombineerd met motionvectoren, zoals hierboven uitgelegd. Vervolgens probeert het neurale netwerk de afbeelding op te schalen naar 4k op basis van de samples en data die in eerdere frames zijn vergaard.
De resultaten daarvan worden vervolgens vergeleken met een vooraf gemaakte 16k-render van dezelfde afbeelding. Informatie uit deze vergelijking wordt daarna doorgevoerd naar het deeplearningalgoritme, waarna het proces zich herhaalt. Dit gebeurt volgens Nvidia miljoenen keren. Het idee daarachter is dat het AI-netwerk gaandeweg leert hoe een high-res afbeelding eruit hoort te zien. Op deze manier leert DLSS ook hoe het algoritme het best de beschikbare informatie en samples kan 'samenstellen' voor het opschalen naar hogere resoluties, en hoe ontbrekende details ingevuld moeten worden. Daarbij leert het deeplearningalgoritme ook hoe het moet omgaan met bewegingen op basis van de motionvectoren, en hoe het eventuele zaken als ghosting en artefacting moet herkennen en corrigeren.
Het uiteindelijke deeplearningnetwerk voor DLSS wordt via de GeForce Ready-drivers van Nvidia geleverd aan RTX-videokaarten, waarna deze kaarten het algoritme kunnen draaien op hun Tensor-cores. In de praktijk wordt een DLSS-game dus gerenderd op de CUDA-cores, met jittering en motionvectoren. Vervolgens worden de frames doorgevoerd naar de Tensor-cores, waar het DLSS-proces plaatsvindt. Daarna vindt postprocessing plaats, waarbij zaken als bloom, motionblur en de hud worden toegevoegd. Het eindresultaat van al die stappen wordt weergegeven op je scherm. Dat proces herhaalt zich bij ieder frame.
Voorheen moest Nvidia voor iedere DLSS-game een eigen neuraal netwerk trainen, maar sinds de introductie van DLSS 2.0 is dat niet langer het geval. In plaats daarvan traint Nvidia een generiek neuraal netwerk, dat in elke game gebruikt kan worden. Dit scheelt een hoop implementatietijd voor gameontwikkelaars, hoewel de implementatie van DLSS nog steeds werk vergt.
Kwaliteitsmodi en schaalfactoren
Eenmaal in-game kunnen gebruikers kiezen uit verschillende 'kwaliteitsmodi'. Onderling verschillen die modi in de scaling factor, oftewel de hoeveelheid upscaling die wordt toegepast. Concreet betekent een hoge schaalfactor dat er een lagere renderresolutie wordt gebruikt, zoals in de onderstaande tabel te zien is. Een hogere kwaliteit met een lagere schaalfactor betekent een betere beeldkwaliteit, maar minder prestatiewinst. Tegelijk leveren hoge schaalfactoren hogere prestatiewinsten op, ten koste van de beeldkwaliteit.
Bij release beschikte DLSS over drie opties: Quality, Balanced en Performance, met schaalfactoren tussen 1,50 en 2,00. Later kwam daar een Ultra Performance-modus bij, met een factor 3. In de praktijk gaf Nvidia aan dat die laatste modus vooral bedoeld is voor gaming op 8k; bij lagere resoluties ligt het aantal inputpixels nogal laag, wat niet ideaal is voor het opschalen.
DLSS-kwaliteitsmodi | |||
---|---|---|---|
Modus | Schaalfactor | Renderschaal | Renderresolutie voor opschalen naar 4k |
Quality | 1,50x | 67% | 2560x1440 pixels |
Balanced | 1,72x | 58% | 2233x1256 pixels |
Performance | 2,00x | 50% | 1920x1080 pixels |
Ultra Performance | 3,00x | 33% | 1280x720 pixels |
Nvidia zelf claimt dat DLSS 2.0 prestatieverbeteringen van meer dan 70 procent kan opleveren, afhankelijk van de gekozen kwaliteitsmodus en de game. Het bedrijf zegt ook dat de beeldkwaliteit daarbij bijna niet te onderscheiden moet zijn van beelden die direct op hoge resolutie gerenderd worden of in sommige gevallen zelfs een betere beeldkwaliteit moeten bieden.
DLSS 2.0 is al enige tijd uit, en in onze ervaring is het inderdaad lastig om een verschil te zien tussen games die native zijn gerenderd en games die zijn opgeschaald met DLSS. Bovendien testen we de DLSS-prestaties van veel RTX-videokaarten op verschillende resoluties, zoals we dat in de afgelopen tijd bijvoorbeeld deden bij de RTX 3090 Ti, RTX 3070 Ti, RTX 3060 en RTX 3050. Ook daar zien we vaak grote framerateverbeteringen.
Voorbeeld: DLSS in Death Stranding
Compatibiliteit en integratie van games
Nu de werking van DLSS duidelijk is, kunnen we het hebben over hoe DLSS in de praktijk gebruikt wordt. DLSS maakt gebruik van Tensor-cores en gebruikers moeten daarom, zoals eerder vermeld, een RTX-videokaart hebben om het te kunnen inzetten. Concreet worden alle videokaarten uit de RTX 20-generatie of nieuwer ondersteund.
DLSS werkt verder alleen in games als ontwikkelaars ondersteuning daarvoor hebben toegevoegd. De techniek is closed source, maar ontwikkelaars kunnen met DLSS uit de voeten door middel van een gratis sdk, waarmee ze de techniek in hun engines en games kunnen verwerken. Daarnaast zijn er relatief kant-en-klare plug-ins voor populaire game-engines als Unreal Engine 4.26 en nieuwer, en Unity 2021.2b en nieuwer. Daarmee is het integreren van DLSS een stuk makkelijker geworden voor kleinere ontwikkelaars.
DLSS is al enige tijd beschikbaar en daarmee is het niet verrassend dat de functie volgens Nvidia al in ruim 150 games zit. Daaronder vallen bijvoorbeeld Call of Duty: Warzone, Doom Eternal, Battlefield 2042, Red Dead Redemption 2, Cyberpunk 2077 en Escape From Tarkov, maar ook meer kleine indietitels als Mortal Online 2, Frozenheim en Pumpkin Jack.