Яку проблему вирішує подвійне чи потрійне буферизація в сучасних іграх?


31

Я хочу перевірити, чи правильне моє розуміння причин використання подвійного (або потрійного) буферизації:

Монітор з оновленням 60 Гц відображає монітор 60 разів на секунду. Якщо монітор оновить дисплей монітора, він оновлює піксель для пікселя та рядок для рядка. Монітор запитує значення кольорів для пікселів з відеопам'яті.

Якщо я зараз запускаю гру, то ця гра постійно маніпулює цією відеопам'яттю.

Якщо ця гра не використовує буферну стратегію (подвійне буферизація тощо), може статися така проблема:

Тепер монітор оновлює свій дисплей монітора. У цей момент монітор уже оновив показ монітора першої половини. У той же час гра маніпулювала відеопам'яттю новими даними. Тепер монітор отримує доступ до другої половини монітора - відображає ці нові маніпульовані дані з відеопам'яті. Проблеми можуть бути сльозотечею або мерехтінням.

Чи правильно я розумію випадки використання буферної стратегії? Чи є інші причини?

Відповіді:


62

По суті, основна мета візуалізації полягає в тому, щоб кожен кадр, який відображається на моніторі, представляв єдине цілісне зображення. Існує кілька різних стратегій, які використовуються або використовуються для досягнення цього.

Далі я згадую "vsync". Vsync - це момент, коли монітор починає малювати нове зображення на екрані; це точка, в якій "vblank" починається на традиційному екрані ЕПТ, де лінія сканування на мить припиняє малювати і повертається назад до верхньої частини монітора. Цей момент дуже важливий для багатьох підходів до узгодження рамки.

"Сльоза" - це те, що ми називаємо це, коли на одному кадрі екран відображає два різних зображення. Якщо, наприклад, я намалював два екранні зображення, які призначені для відображення один за одним, але натомість монітор відобразив верхню половину кадру, а нижню половину кадру - це "розрив". Це відбувається через зміну даних, з яких читає монітор, поки монітор малює, а не під час vblank. (У сучасних програмах це зазвичай відбувається, тому що користувач відключив очікування vsync у своїх налаштуваннях драйвера)

Нульовий буфер

На найстарішому апаратному забезпеченні часто не вистачало пам’яті, щоб вмістити зображення в повноекранному режимі, і тому замість того, щоб малювати екранне зображення, вам потрібно було вказати кольори для кожної лінії сканування окремо, тоді як монітор був у процесі малювання цієї лінії. Наприклад, на Atari 2600 у вас було всього 76 машинних циклів інструкцій, щоб визначити, який колір входив у кожен піксель лінії сканування, перш ніж телебачення почало насправді малювати цю лінію. І тоді у вас було 76 циклів інструкцій, щоб забезпечити вміст для наступного сканування тощо.

Одно буферний

Коли ви малюєте в контексті "одного буфера", ви малюєте прямо в VRAM, з якого читається монітор. При такому підході ви "змагаєтесь зі сканером". Основна ідея полягає в тому , що , коли Scanline починає малювати вміст попереднього фрейму, у верхній частині екрану, ви малюєте в VRAM позаду нього. Отже, поки лінія сканування малює екранне зображення для останнього кадру, ви малюєте наступний кадр позаду.

Взагалі ви намагаєтеся закінчити малювати зображення наступного кадру до того, як лінія сканування "обмине" вас, повторившись і обганяючи пікселі, які ви малюєте, а також ніколи не випереджати лінію сканування, інакше ваш новий кадр може вписатись у те, що повинно було бути попереднім.

З цієї причини візуалізація з одним буфером зазвичай працювала шляхом малювання сканувань, зверху вниз та зліва направо. Якщо ви намалювали в іншому порядку, ймовірно, що лінія сканування знову з’явиться і помітить шматочки «наступного» зображення, яке ви ще не отримали для малювання.

Зауважте, що в сучасних операційних системах ви, як правило, ніколи не маєте можливості малювати однобуферні, хоча це було досить часто тридцять років тому. (Боже, я зараз відчуваю себе старим - це те, що я робив, коли вперше почав розробляти ігри)

Двомісний буфер

Це набагато, набагато простіше, ніж будь-яка зі стратегій, що були раніше.

У системі подвійної буферизації у нас достатньо пам'яті для зберігання двох різних зображень на екрані, і тому ми позначаємо один з них як "передній буфер", а другий - "задній буфер". "Передній буфер" - це те, що зараз відображається, а "задній буфер" - це те, де ми зараз малюємо.

Після того як ми закінчимо малювати екранне зображення до заднього буфера, ми чекаємо, поки vsync, а потім поміняємо два буфери. Таким чином, задній буфер стає переднім буфером, і навпаки, і весь своп відбувався, поки монітор нічого не малював.

Потрійний буфер

Одне питання, яке часто виникає з подвійними буферними підходами, - це те, що після того, як ми закінчимо малювання до заднього буфера, нам доведеться просто посидіти, чекаючи vsync, перш ніж ми зможемо поміняти буфери та продовжувати працювати; ми могли за цей час робити розрахунки! Більше того, весь час, коли ми чекаємо на обмін між буферами, зображення в цьому зворотному буфері старіє і старіє, тим самим збільшуючи сприйняті користувачем затримки.

У системах з потрійним буфером ми створюємо собі три буфери - один передній буфер і два задні буфери. Ідея така:

На моніторі відображається передній буфер, а ми втягуємося в задній буфер №1. Якщо ми закінчимо малювання у зворотному буфері №1 до того, як монітор закінчить малювати передній буфер, то замість того, щоб чекати vsync, ми замість цього негайно починаємо малювати наступний кадр у задньому буфері №2. Якщо ми закінчимо, і vsync досі не прийшов, ми починаємо малювати назад у зворотний буфер №1 тощо. Ідея полягає в тому, що коли vsync врешті-решт станеться, той чи інший з наших задніх буферів буде повним, і що можна замінити його на передній буфер.

Перевага потрійного буферизації полягає в тому, що ми не втрачаємо часу, який ми витратили на очікування vsync при підході подвійного буферизації, і зображення, замінене на передній буфер, може бути «свіжішим», ніж той, який чекав на vsync для 8 мс. Нижня частина потрійного буферизації полягає в тому, що нам потрібна додаткова пам'ять для зберігання додаткового зображення на екрані, а також використання нашого процесора / GPU буде вище (знову ж таки, оскільки ми не сповільнюємось, щоб чекати vsync).

Зазвичай сучасні водії часто виконують трійну буферизацію прозоро, поза кадром. Ви пишете свій код, щоб зробити подвійну буферизацію, і драйвер насправді поверне вам управління рано, і просто внутрішньо обміняєтесь обміном між якими б то не було зворотними буферами, які він хоче використовувати, без того, щоб ваш код ніколи про це не знав.

Наразі постачальники GPU рекомендують не здійснювати потрійну буферизацію самостійно - драйвер зробить це за вас автоматично.


7
Це неймовірно детальна відповідь і пояснює, чому багато речей робляться такими, якими вони є (як, наприклад, простір координат екрана тощо). Також відповів на моє запитання "чому не чотириразові буфери? Чотирьох?" Я не усвідомлював, що заміна буфера відбувається у фоновому режимі, це означає, що два зворотних буфера - це максимум необхідного. Отримано.
обідне м’ясо317

Насправді існує чотирифазна буферизація. Це подвійне буферування для стереоскопічного перегляду. swiftless.com/tutorials/opengl/smooth_rotation.html
Нарек

@Narek Ні. Посилаючись на ваше посилання: "Ви не можете реально включити фактичну квадратичну буферизацію в середовищі комп'ютерної графіки, оскільки немає реальної точки". Запропонувати те, що робити подвійне буферизація на двох різних видах одночасно було б "чотирифазним буферизацією" - це просто забавне гра гри; не щось справжнє.
Тревор Пауелл

@TrevorPowell Додаючи частину, яку ви забули включити: "Ну, як правило, чотирифазна буферизація стосується подвійної буферизації в стереоскопічному середовищі. Наприклад: у вас є два дисплеї, як правило, для 3D-цілей, і кожне око є подвійним буферизованим." Тепер контекст може бути більш чітким.
Нарек

@TrevorPowell Ваша думка, але це абсолютно зрозуміло. Немає сенсу мати більше 3 буферів для одного буфера візуалізації.
Нарек
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.