reinterpretcast
I ovenstående eksempel kan det umiddelbart se ud som om en opdateringshastighed på 0,26 Hz og en framerate på 0,2 FPS (Frames Per Second) er tæt nok til at vise korrekt, men det er tydeligt, når man ser demokøbet, at de to er helt ude af synkronisering, og derfor forekommer screen tearing regelmæssigt.
Det virkelige problem med dette eksempel er, at det er et “single-buffered-program”. Vi skriver vores frames direkte til den buffer, der føres til skærmen, og når skærmen ønsker at opdatere sit billede, er der derfor en risiko for, at den får en frame, der ikke er helt færdig endnu. I en rigtig applikation kan frameraten ofte ændre sig dramatisk afhængigt af visse omstændigheder, hvilket kan forværre dette problem i single-buffered applikationer og gøre screen tearing endnu mere uforudsigeligt.
Double Buffering
En måde at afhjælpe nogle af disse problemer på er ved at bruge double-buffering. Denne tegningsmetode består i at skrive rammedataene til en bagbuffer og derefter kun kopiere dem over i den primære buffer (videofeed til skærmen), når en ramme er færdig. På denne måde vil brugeren aldrig se nogen halvfærdige rammer, ikke sandt? Forkert.
Mens screen tearing har tendens til at blive reduceret betydeligt med dobbeltbuffering, tager det tid at kopiere data, og det er derfor helt muligt, at skærmen opdaterer sit billede halvvejs gennem buffer-kopieringsprocessen! Dette problem kan visualiseres præcis som single-buffered tearing – i den foregående demo skal du blot forestille dig, at de pixels, der skrives ind i den primære buffer, ikke genereres direkte af grafikkortet, men i stedet placeres i bufferen sekventielt som resultat af en kopieringsoperation fra en sekundær buffer.
Double Buffering + VSync
En anden lindringstaktik er at bruge VSync. VSync er en forkortelse for “vertikal synkronisering” og fungerer ved kun at lade den sekundære buffer skrive til den primære buffer lige efter, at skærmen er blevet opdateret. Håbet er, at buffer-kopieringsoperationen skal være afsluttet inden den næste opdatering. Dette virker ved at reducere screen tearing dramatisk, men har dog sine problemer.
Hvis du har et program med høj framerate, vil VSync normalt fungere perfekt. Din framerate er begrænset til skærmens opdateringshastighed, men det er fint nok, fordi skærmen alligevel ville vise med den hastighed. Problemet opstår, når du opnår en lavere framerate end skærmens opdateringsfrekvens.
Sig, at du opnår 60 FPS på en 75 Hz-skærm – det betyder, at billedbufferen opdateres med 80 % af opdateringsfrekvensen. Hvis VSync er aktiveret, skal rammer kopieres til skærmbufferen med en underopdeling af opdateringsfrekvensen. I dette tilfælde vil programmet misse “deadline” ved hver anden cyklus, så vi ender med at få halvdelen af opdateringshastigheden som vores framerate: 37,5 FPS. Dette er betydeligt mindre end de 60 FPS, som grafikkortet kan opnå.
Tilbage til TL;DR for VSync med dobbeltbuffer er, at hvis du opnår en konstant højere FPS end din opdateringsfrekvens, kan det være en god idé til at reducere screen tearing, men hvis FPS vil falde under skærmens opdateringsfrekvens, kan VSync reducere FPS betydeligt.
Triple Buffering + VSync
Den hellige gral i hele dette rod er normalt triple buffering med VSync. Grænsen for VSync med dobbelt buffering er, at frameraten kan falde betydeligt på grund af den tid, der bruges på at vente på det rigtige tidspunkt til at kopiere den sekundære buffer ind i den primære buffer. At vente er ofte ikke en fantastisk idé i datalogi, hvor det kan undgås, så en løsning her er blot at tilføje endnu en buffer.
Med tre buffere kan de to bagbuffere trækkes til skiftevis, så det altid er sådan, at den ene buffer er færdig og den anden er i gang. Det betyder, at lige efter en skærmopdatering kan den buffer, der i øjeblikket er færdig, kopieres til den primære buffer – hvilket giver fordelene ved VSync uden den tidligere omtalte ulempe ved frameraten.
Den største ulempe ved triple buffering, hvor den er tilgængelig i programmer, er, at den optager mere hukommelse – hvis vi taler om grafikkort, betyder det mere VRAM (Video RAM). Dette er hurtig hukommelse, der bruges direkte af grafikkortet, og derfor kan triple buffering i nogle tilfælde medføre et betydeligt FPS-fald, mens RAM med højere latenstid bruges til at kompensere for manglen på native VRAM. Typisk er dette ikke et stort problem, da mængden af hukommelse, der optages af den tredje buffer, ofte er lille i forhold til den samlede størrelse af VRAM, men VSync med kun to buffere kan give en bedre framerate i nogle meget niche tilfælde! Svingninger og karruseller, ikke sandt?