reinterpretcast
In het bovenstaande voorbeeld lijkt het er in eerste instantie op dat een refresh rate van 0.26 Hz en een framerate van 0.2 FPS (Frames Per Second) dicht genoeg bij elkaar liggen om correct weer te geven, maar het is duidelijk als je de demo ziet lopen dat de twee volledig niet synchroon lopen en dus treedt er regelmatig screen tearing op.
Het echte probleem met dit voorbeeld is dat het een ‘single-buffered applicatie’ is. We schrijven onze frames direct naar de buffer die naar het beeldscherm wordt gevoerd, en wanneer het beeldscherm zijn beeld wil verversen, bestaat dus het risico dat het een frame krijgt dat nog niet helemaal af is. In een echte toepassing kan de framerate vaak dramatisch veranderen afhankelijk van bepaalde omstandigheden, wat dit probleem in single-buffered toepassingen kan verergeren en screen tearing nog onvoorspelbaarder kan maken.
Double Buffering
Een manier om sommige van deze problemen te verlichten is het gebruik van double-buffering. Deze tekenmethode bestaat uit het schrijven van de framedata naar een backbuffer, en deze dan pas naar de primaire buffer (de video-feed naar het beeldscherm) te kopiëren als een frame compleet is. Op deze manier zal de gebruiker nooit half voltooide frames zien, toch? Fout.
Terwijl het scheuren van het scherm aanzienlijk wordt verminderd met dubbele buffering, kost het kopiëren van gegevens tijd, en als zodanig is het volkomen mogelijk dat de monitor zijn beeld halverwege het bufferkopieerproces vernieuwt! Dit probleem kan precies zo worden gevisualiseerd als bij single-buffered tearing – stel je bij de vorige demo voor dat de pixels die in de primaire buffer worden geschreven niet direct door de grafische kaart worden gegenereerd, maar in plaats daarvan sequentieel in de buffer worden geplaatst als resultaat van een kopieeroperatie vanuit een secundaire buffer.
Double Buffering + VSync
Een andere verlichtingstactiek is het gebruik van VSync. VSync is de afkorting van ‘vertical synchronisation’. VSync werkt door de achterste buffer pas naar de primaire buffer te laten schrijven nadat het beeldscherm is ververst. De hoop is dat de kopieeroperatie van de buffer voltooid moet zijn voor de volgende verversing. Dit werkt in het drastisch verminderen van scherm tearing, maar heeft zijn problemen.
Als u een toepassing met een hoge framesnelheid heeft, zal VSync meestal perfect werken. Uw framerate is beperkt tot de refresh rate van uw monitor, maar dat is prima omdat uw monitor toch al op die snelheid zou weergeven. Het probleem ontstaat wanneer u een lagere framerate haalt dan de verversingssnelheid van uw beeldscherm.
Stel dat u 60 FPS haalt op een 75 Hz monitor – dat betekent dat de framebuffer op 80% van de verversingssnelheid wordt bijgewerkt. Als VSync is ingeschakeld, moeten frames naar de schermbuffer worden gekopieerd met een onderverdeling van de verversingsfrequentie. In dit geval zal de applicatie om de andere cyclus de ‘deadline’ missen, dus zullen we eindigen met de helft van de verversingsfrequentie als onze framerate: 37.5 FPS. Dit is aanzienlijk minder dan de 60 FPS die de grafische kaart kan bereiken.
De TL;DR voor double-buffered VSync is dat als u een consistent hogere FPS bereikt dan uw verversingssnelheid, het een goed idee kan zijn voor het verminderen van schermtearing, maar als de FPS onder de verversingssnelheid van uw scherm zal dalen, kan VSync de FPS aanzienlijk verminderen.
Drievoudige buffering + VSync
De heilige graal van deze hele puinhoop is meestal drievoudige buffering met VSync. De limiet van VSync met dubbele buffering is dat de framerate aanzienlijk kan dalen door de tijd die wordt besteed aan het wachten op het juiste moment om de secundaire buffer naar de primaire buffer te kopiëren. Wachten is vaak geen fantastisch idee in de informatica waar het vermeden kan worden, dus een oplossing hier is om gewoon nog een buffer toe te voegen.
Met drie buffers kunnen de twee achterste buffers om beurten worden aangesproken, zodat het altijd zo is dat één buffer compleet is en één in uitvoering. Dit betekent dat net na een monitorverversing de buffer die op dat moment compleet is, kan worden gekopieerd naar de primaire buffer – dit biedt de voordelen van VSync zonder het eerder besproken framerate-nadeel.
Het belangrijkste nadeel van drievoudige buffering waar het beschikbaar is in toepassingen, is dat het meer geheugen in beslag neemt – als we het hebben over grafische kaarten, betekent dit meer VRAM (Video RAM). Dit is snel geheugen dat rechtstreeks door de grafische kaart wordt gebruikt, en dus kan drievoudige buffering in sommige gevallen een aanzienlijke FPS-daling veroorzaken terwijl RAM met een hogere latentie wordt gebruikt om het gebrek aan native VRAM goed te maken. Doorgaans is dit geen groot probleem omdat de hoeveelheid geheugen die de derde buffer inneemt vaak klein is in vergelijking met de totale grootte van het VRAM, maar VSync met slechts twee buffers kan in sommige zeer niche gevallen een betere framerate opleveren! Schommelingen en rotondes, eh?