reinterpretcast
I exemplet ovan kan det till en början verka som om en uppdateringsfrekvens på 0,26 Hz och en framerate på 0,2 FPS (Frames Per Second) skulle ligga tillräckligt nära varandra för att visa korrekt, men när man tittar på demokörningen är det uppenbart att de två är helt osynkroniserade och att screen tearing därför inträffar regelbundet.
Den verkliga problematiken med det här exemplet är att det är en ”single-buffered application”. Vi skriver våra ramar direkt till den buffert som matas till skärmen, och när skärmen vill uppdatera sin bild finns det en risk att den får en ram som inte är helt färdig ännu. I en riktig tillämpning kan frameraten ofta ändras dramatiskt beroende på vissa omständigheter, vilket kan förvärra det här problemet i single-buffered-applikationer och göra screen tearing ännu mer oförutsägbart.
Double Buffering
Ett sätt att lindra en del av de här problemen är att använda sig av double-buffering. Denna ritningsmetod går ut på att skriva bilddata till en bakre buffert och sedan kopiera över den till den primära bufferten (videotillförseln till skärmen) först när en bild är klar. På så sätt kommer användaren aldrig att se några halvfärdiga ramar, eller hur? Fel.
Som skärmutslag tenderar att minskas avsevärt med dubbel buffertning, tar det tid att kopiera data, och därför är det fullt möjligt att bildskärmen uppdaterar sin bild halvvägs genom buffertkopieringen! Det här problemet kan visualiseras precis som vid enkelbuffrad tearing – i den tidigare demonstrationen kan du bara föreställa dig att de pixlar som skrivs in i den primära bufferten inte genereras direkt av grafikkortet, utan istället placeras i bufferten sekventiellt som ett resultat av en kopieringsoperation från en sekundärbuffert.
Dubbelbuffring + VSync
En ytterligare lindringstaktik är att använda VSync. VSync är en förkortning för ”vertikal synkronisering” och fungerar genom att den bakre bufferten endast får skriva till den primära bufferten direkt efter det att skärmen har uppdaterats. Förhoppningen är att kopieringen av bufferten ska vara klar innan nästa uppdatering. Detta fungerar för att dramatiskt minska skärmtårar, men har sina problem.
Om du har ett program med hög framerate kommer VSync vanligtvis att fungera perfekt. Din framerate är begränsad till skärmens uppdateringsfrekvens, men det är okej eftersom skärmen ändå skulle visa med den frekvensen. Problemet uppstår när du uppnår en lägre framerate än skärmens uppdateringsfrekvens.
Säg att du uppnår 60 FPS på en 75 Hz-skärm – det betyder att bildbufferten uppdateras med 80 % av uppdateringsfrekvensen. Om VSync är aktiverat måste ramarna kopieras till skärmbufferten med en underindelning av uppdateringsfrekvensen. I det här fallet kommer programmet att missa ”tidsfristen” vid varannan cykel, så vi hamnar med halva uppdateringsfrekvensen som vår framerate: 37,5 FPS. Detta är betydligt mindre än de 60 FPS som grafikkortet kan uppnå.
The TL;DR för VSync med dubbelbuffert är att om du uppnår ett konsekvent högre FPS än uppdateringsfrekvensen kan det vara en bra idé för att minska skärmtårar, men om FPS kommer att sjunka under uppdateringsfrekvensen för din skärm kan VSync minska FPS avsevärt.
Triple Buffering + VSync
Den heliga graalen i hela den här röran är vanligtvis triple buffering med VSync. Gränsen för VSync med dubbel buffring är att bildfrekvensen kan minska avsevärt på grund av den tid som går åt till att vänta på rätt tidpunkt för att kopiera den sekundära bufferten till den primära bufferten. Att vänta är ofta ingen fantastisk idé inom datavetenskap där det kan undvikas, så en lösning här är att helt enkelt lägga till ytterligare en buffert.
Med tre buffertar kan de två bakre buffertarna dras till växelvis så att det alltid är så att en buffert är färdig och en är på gång. Detta innebär att precis efter en bildskärmsuppdatering kan den buffert som för närvarande är färdig kopieras till den primära bufferten – vilket ger fördelarna med VSync utan den nackdel för bildfrekvensen som tidigare diskuterats.
Den största nackdelen med trippelbuffring där den finns tillgänglig i tillämpningar är att den tar mer minne i anspråk – om vi pratar om grafikkort innebär detta mer VRAM (Video RAM). Detta är snabbt minne som används direkt av grafikkortet, och därför kan trippelbuffring i vissa fall orsaka en betydande minskning av FPS medan RAM med högre latens används för att kompensera bristen på inhemskt VRAM. Vanligtvis är detta inte ett stort problem eftersom mängden minne som tas upp av den tredje bufferten ofta är liten i jämförelse med den totala storleken på VRAM, men VSync med endast två buffertar kan ge en bättre framerate i vissa mycket nischade fall! Det är en del av det som är viktigt, eller hur?