Masalah apa yang dipecahkan oleh buffer ganda atau tripel dalam game modern?

31

Saya ingin memeriksa apakah pemahaman saya tentang penyebab penggunaan buffer ganda (atau tiga) benar:

Monitor dengan penyegaran 60Hz adalah monitor-display 60 kali per detik. Jika monitor memperbarui layar monitor, ia memperbarui piksel untuk piksel dan garis untuk garis. Monitor meminta nilai warna untuk piksel dari memori video.

Jika saya menjalankan game sekarang, maka game ini terus memanipulasi memori video ini.

Jika game ini tidak menggunakan strategi buffer (buffering ganda dll.) Maka masalah berikut dapat terjadi:

Monitor sekarang menyegarkan tampilan monitornya. Pada saat ini monitor sudah menyegarkan layar monitor babak pertama. Pada saat yang sama, gim ini memanipulasi memori video dengan data baru. Sekarang monitor mengakses monitor paruh kedua - menampilkan data yang dimanipulasi baru ini dari memori video. Masalahnya bisa merobek atau berkedip.

Apakah pemahaman saya tentang kasus menggunakan strategi buffer benar? Apakah ada alasan lain?

krokvskrok
sumber

Jawaban:

62

Pada dasarnya, tujuan inti dalam rendering adalah untuk setiap frame yang ditampilkan pada monitor untuk menghadirkan gambar tunggal yang koheren. Ada beberapa strategi berbeda yang, atau dulu, digunakan untuk mencapai ini.

Berikut ini, saya menyebutkan "vsync". Vsync adalah saat di mana monitor mulai menggambar gambar layar baru; itu adalah titik di mana "vblank" dimulai pada layar CRT tradisional, di mana garis pemindaian berhenti menggambar dan bergerak kembali ke bagian atas monitor. Momen ini sangat penting bagi banyak pendekatan untuk membingkai koherensi.

"Merobek" adalah apa yang kita sebut ketika layar merender dari dua gambar yang berbeda, dalam satu bingkai. Jika, misalnya, saya telah menggambar dua gambar layar yang dimaksudkan untuk ditampilkan satu demi satu, tetapi monitor malah menampilkan bagian atas bingkai satu, dan bagian bawah bingkai dua, itu "merobek". Ini terjadi karena mengubah data yang dibaca monitor saat monitor menggambar, alih-alih selama vblank. (Dalam program modern, ini biasanya terjadi karena pengguna dinonaktifkan menunggu vsync dalam pengaturan driver mereka)

Zero-Buffer

Pada perangkat keras tertua, sering kali tidak ada cukup memori untuk menyimpan gambar layar penuh, dan alih-alih menggambar gambar layar, Anda perlu menentukan warna untuk setiap garis pemindaian secara individual, sementara monitor sedang dalam proses menggambar garis itu. Pada Atari 2600, misalnya, Anda hanya memiliki 76 siklus instruksi mesin untuk menentukan warna apa yang masuk ke setiap piksel garis pemindaian, sebelum televisi mulai benar-benar menggambar garis pemindaian itu. Dan kemudian Anda memiliki 76 siklus instruksi untuk menyediakan konten untuk pemindaian berikutnya , dan seterusnya.

Penyangga Tunggal

Saat menggambar dalam konteks "buffer tunggal", Anda menggambar langsung ke VRAM yang sedang dibaca dari monitor. Dalam pendekatan ini, Anda "berlomba memindai". Gagasan umum adalah bahwa ketika garis pemindaian mulai menggambar konten bingkai sebelumnya di bagian atas layar, Anda menggambar VRAM di belakangnya . Jadi saat scanline sedang menggambar gambar layar untuk frame terakhir, Anda menggambar frame berikutnya di belakang scanline.

Secara umum, Anda mencoba untuk menyelesaikan menggambar gambar frame-berikutnya sebelum scanline "lap" Anda dengan datang lagi dan menyalip piksel yang Anda gambar, dan juga untuk tidak pernah maju dari scanline, atau yang baru Anda bingkai mungkin menggambarkan apa yang seharusnya menjadi bingkai sebelumnya.

Karena alasan ini, rendering buffer tunggal biasanya bekerja sendiri dengan menggambar scanlines, dari atas ke bawah, dan dari kiri ke kanan. Jika Anda menggambar dengan urutan lain, ada kemungkinan bahwa garis pemindaian akan muncul lagi dan melihat bit dari gambar "selanjutnya" yang belum sempat Anda gambar.

Perhatikan bahwa dalam sistem operasi modern, Anda biasanya tidak pernah memiliki kesempatan untuk menggambar buffer tunggal, meskipun ini cukup umum tiga puluh tahun yang lalu. (Astaga, saya merasa tua sekarang - ini adalah apa yang saya lakukan ketika saya mulai dalam pengembangan game)

Penyangga Ganda

Ini jauh, jauh lebih sederhana daripada salah satu strategi yang datang sebelumnya.

Dalam sistem buffer ganda, kami memiliki cukup memori untuk menyimpan dua gambar layar yang berbeda, dan kami menunjuk salah satu dari mereka sebagai "buffer depan" dan yang lainnya, "buffer belakang". "Penyangga depan" adalah yang sedang ditampilkan, dan "penyangga belakang" adalah tempat kami saat ini menggambar.

Setelah kami selesai menggambar gambar layar ke buffer belakang, kami menunggu sampai vsync, dan kemudian menukar kedua buffer. Dengan cara ini, buffer belakang menjadi buffer depan, dan sebaliknya, dan seluruh swap terjadi saat monitor tidak menggambar apa pun.

Penyangga Tiga Kali Lipat

Satu masalah yang sering diangkat dengan pendekatan buffer ganda adalah bahwa setelah kita selesai menggambar ke buffer belakang, kita harus duduk diam menunggu vsync sebelum kita dapat menukar buffer dan terus bekerja; kita bisa melakukan perhitungan selama waktu itu! Terlebih lagi, setiap saat kami menunggu untuk bertukar di antara buffer, gambar di buffer belakang semakin lama dan semakin tua, sehingga meningkatkan latensi yang dirasakan pengguna.

Dalam sistem triple-buffer, kami membuat sendiri tiga buffer - satu buffer depan dan dua buffer belakang. Idenya adalah ini:

Monitor menampilkan buffer depan, dan kami sedang menggambar buffer belakang # 1. Jika kita selesai menggambar ke buffer belakang # 1 sebelum monitor selesai menggambar buffer depan, maka alih-alih menunggu vsync, kita malah segera mulai menggambar frame berikutnya ke buffer belakang # 2. Jika kita selesai dan vsync masih belum datang, kita mulai menggambar kembali ke buffer belakang # 1, dan seterusnya. Idenya adalah bahwa ketika vsync akhirnya terjadi, satu atau yang lain dari buffer belakang kita akan lengkap, dan yang satu dapat ditukar dengan buffer depan.

Manfaat dari triple-buffering adalah kita tidak kehilangan waktu yang kita habiskan untuk menunggu vsync dalam pendekatan double-buffering, dan gambar yang ditukar ke buffer depan mungkin "lebih segar" daripada yang telah menunggu vsync untuk 8ms. Kelemahan dari triple-buffering adalah kita membutuhkan memori ekstra untuk menyimpan gambar layar tambahan, dan penggunaan CPU / GPU kita akan lebih tinggi (sekali lagi, karena kita tidak memperlambat untuk menunggu vsync).

Biasanya, driver modern akan sering melakukan triple-buffering secara transparan, di belakang layar. Anda menulis kode Anda untuk melakukan buffering ganda, dan driver sebenarnya akan mengembalikan kontrol kepada Anda lebih awal, dan hanya secara internal menangani pertukaran antara berapa banyak buffer belakang yang ingin digunakan, tanpa kode Anda pernah menyadarinya.

Vendor GPU saat ini merekomendasikan Anda untuk tidak menerapkan triple-buffering sendiri - driver akan melakukannya untuk Anda secara otomatis.

Trevor Powell
sumber
7
Ini adalah jawaban yang sangat terperinci, dan menjelaskan mengapa banyak hal dilakukan seperti itu (seperti ruang koordinat layar, dll). Juga menjawab pertanyaan saya, "mengapa tidak buffer empat kali lipat? Quintuple?" Saya tidak menyadari bahwa swapping buffer terjadi di latar belakang, artinya dua buffer belakang adalah yang paling dibutuhkan. Terpilih.
lunchmeat317
Sebenarnya ada quad buffering. Ini adalah buffering ganda untuk tampilan stereoskopik. swiftless.com/tutorials/opengl/smooth_rotation.html
Narek
@Narek No. Mengutip dari tautan Anda: "Anda tidak dapat benar-benar mengaktifkan buffering quad aktual di lingkungan grafik komputer karena tidak ada titik nyata". Menyarankan bahwa melakukan buffering ganda pada dua tampilan berbeda secara bersamaan adalah "quad buffering" adalah permainan kata yang lucu; bukan sesuatu yang nyata.
Trevor Powell
@TrevorPowell Menambahkan bagian yang Anda lupa sertakan: "Yah, biasanya buffering mengacu pada buffering ganda dalam lingkungan stereoskopik. Misalnya: Anda memiliki dua tampilan, biasanya untuk tujuan 3D dan setiap mata buffered ganda." Sekarang konteksnya mungkin lebih jelas.
Narek
@ TrevorPowell Poin Anda benar-benar jelas. Tidak masuk akal untuk memiliki lebih dari 3 buffer untuk satu buffer render.
Narek