Saya memiliki aplikasi uji OpenGL sederhana dalam C yang menggambar berbagai hal sebagai respons terhadap input kunci. (Mesa 8.0.4, dicoba dengan Mesa-EGL dan dengan GLFW, Ubuntu 12.04LTS pada PC dengan NVIDIA GTX650). Gambarnya cukup sederhana / cepat (rotating triangle stuff of stuff). Kode pengujian saya tidak membatasi framerate dengan cara apa pun, hanya terlihat seperti ini:
while (true)
{
draw();
swap_buffers();
}
Saya telah menghitung waktu ini dengan sangat cermat, dan saya menemukan bahwa waktu dari satu eglSwapBuffers()
(atau glfwSwapBuffers
, hal yang sama) panggilan ke yang berikutnya adalah ~ 16,6 milidetik. Waktu dari setelah panggilan ke eglSwapBuffers()
sebelum panggilan berikutnya hanya sedikit kurang dari itu, meskipun apa yang diambil sangat sederhana. Waktu yang dibutuhkan panggilan swap buffer berada di bawah 1ms.
Namun, waktu dari aplikasi mengubah apa yang digambarkan sebagai respons terhadap penekanan tombol terhadap perubahan yang sebenarnya muncul di layar adalah> 150ms (sekitar 8-9 nilai bingkai). Ini diukur dengan rekaman kamera dari layar dan keyboard pada 60fps.
Karena itu, pertanyaannya:
Di mana drawed buffered antara panggilan untuk swap buffer dan benar-benar muncul di layar? Kenapa ditunda? Tampaknya aplikasi ini menggambar banyak bingkai di depan layar setiap saat.
Apa yang dapat dilakukan aplikasi OpenGL untuk menyebabkan undian langsung ke layar? (Yaitu: tidak ada buffering, cukup blok sampai draw selesai; Saya tidak perlu throughput tinggi, saya perlu latensi rendah)
Apa yang bisa dilakukan aplikasi untuk membuat penarikan langsung di atas secepat mungkin?
Bagaimana aplikasi mengetahui apa yang sebenarnya ada di layar sekarang? (Atau, berapa lama / berapa banyak frame penundaan buffering saat ini?)
Jawaban:
Setiap fungsi menggambar API yang dipanggil dari CPU akan dikirimkan ke buffer cincin perintah GPU untuk dieksekusi nanti oleh GPU. Ini berarti bahwa fungsi OpenGL sebagian besar adalah fungsi non-blocking. Jadi CPU dan GPU akan bekerja secara paralel.
Yang paling penting untuk diperhatikan adalah aplikasi Anda bisa terikat CPU atau GPU. setelah Anda memanggil glFinish, CPU harus menunggu GPU untuk menyelesaikan perintah menggambarnya, jika GPU membutuhkan lebih banyak waktu dan dapat menyebabkan CPU berhenti maka aplikasi Anda terikat GPU. Jika GPU selesai menggambar perintah dan CPU terlalu lama untuk glFinish maka aplikasi Anda terikat CPU.
Dan perhatikan bahwa ada perbedaan antara
glFlush
danglFinish
.glFlush
: menunjukkan bahwa semua perintah yang sebelumnya telah dikirim ke GL harus diselesaikan dalam waktu yang terbatas.glFinish
: memaksa semua perintah GL sebelumnya untuk menyelesaikan. Selesai tidak kembali sampai semua efek dari perintah yang dikeluarkan sebelumnya pada klien GL dan keadaan server dan framebuffer sepenuhnya direalisasikan. "glXSwapBuffers melakukan glFlush implisit sebelum kembali. Perintah OpenGL berikutnya dapat dikeluarkan segera setelah memanggil glXSwapBuffers, tetapi tidak dieksekusi sampai pertukaran buffer selesai.
Kerangka waktu yang sebenarnya kemungkinan besar akan ditentukan oleh mana dari dua CPU / GPU ini mengambil lebih banyak waktu untuk menyelesaikan pekerjaannya.
sumber
both low framerate (exactly same as monitor refresh rate??
tidak, kecuali jika Anda secara eksplisit menggunakan VSync.OpenGL tidak pernah memperbarui layar, secara teknis.
Ada sistem API jendela yang terpisah dari GL (misalnya GLX, WGL, CGL, EGL) yang melakukan ini. Buffer swap menggunakan API ini umumnya secara implisit meminta
glFlush (...)
tetapi dalam beberapa implementasi (misalnya rasterizer GDI pada Windows) ia melakukan penuhglFinish (...)
:* Di sisi kiri, adalah jalur ICD (perangkat keras)
SwapBuffers (...)
. Di sisi kanan, jalur GDI (perangkat lunak).Jika Anda mengaktifkan VSYNC dan buffer ganda, maka perintah apa pun yang akan memodifikasi back buffer sebelum terjadi swap yang tertunda harus berhenti hingga swap. Ada kedalaman terbatas pada antrian perintah, jadi perintah yang macet ini pada akhirnya akan menyebabkan kemacetan di dalam pipa. Ini bisa berarti bahwa alih-alih memblokir
SwapBuffers (...)
aplikasi Anda sebenarnya memblokir beberapa perintah GL yang tidak terkait sampai VBLANK berputar. Apa yang sebenarnya menjadi intinya adalah berapa banyak buffer yang Anda miliki dalam rantai swap Anda.Selama semua buffer belakang penuh dengan frame jadi yang belum dipindahkan ke depan, swap buffer secara implisit akan menyebabkan pemblokiran. Sayangnya, tidak ada cara untuk secara eksplisit mengontrol jumlah buffer belakang yang digunakan oleh sebagian besar API sistem jendela GL (selain 0 buffer tunggal atau 1 buffer ganda). Pengemudi bebas menggunakan 2 buffer belakang jika diinginkan (triple buffering), tetapi Anda tidak dapat meminta ini pada tingkat aplikasi menggunakan sesuatu seperti GLX atau WGL.
sumber
glFinish (...)
segera setelah menukar buffer. Ini akan menghapus antrian perintah, tetapi itu juga berarti bahwa GPU dan CPU akan disinkronkan (yang tidak baik jika Anda ingin menjaga GPU tetap bekerja setiap saat).Saya menganggap Anda terbiasa dengan eksperimen ini ?
Pada dasarnya John Carmack melakukan sesuatu yang serupa, merekam layar dan timing pixel yang dikirim ke layar. Dia menemukan bahwa banyak latensi datang dari layar. Faktor lainnya adalah keterlambatan input dari keyboard, driver video dan atau tentu saja pelaksanaan program itu sendiri.
sumber