Saya mengalami masalah dalam membedakan perbedaan praktis antara menelepon glFlush()
dan glFinish()
.
Docs mengatakan bahwa glFlush()
dan glFinish()
akan mendorong semua operasi yang di-buffer ke OpenGL sehingga seseorang dapat yakin semuanya akan dieksekusi, perbedaannya adalah yang glFlush()
langsung mengembalikan di mana sebagai glFinish()
blok sampai semua operasi selesai.
Setelah membaca definisinya, saya membayangkan bahwa jika saya menggunakannya glFlush()
, saya mungkin akan mengalami masalah dalam mengirimkan lebih banyak operasi ke OpenGL daripada yang bisa dijalankannya. Jadi, hanya untuk mencoba, saya menukar saya glFinish()
untuk a glFlush()
dan lihatlah, program saya berjalan (sejauh yang saya tahu), persis sama; frekuensi gambar, penggunaan sumber daya, semuanya sama.
Jadi saya bertanya-tanya apakah ada banyak perbedaan antara kedua panggilan tersebut, atau jika kode saya membuatnya berjalan tidak berbeda. Atau di mana salah satu harus digunakan vs. yang lain. Saya juga membayangkan bahwa OpenGL akan memiliki beberapa panggilan glIsDone()
untuk memeriksa apakah semua perintah yang di-buffer untuk a glFlush()
lengkap atau tidak (jadi seseorang tidak mengirim operasi ke OpenGL lebih cepat daripada yang dapat dijalankan), tetapi saya tidak dapat menemukan fungsi seperti itu .
Kode saya adalah loop permainan yang khas:
while (running) {
process_stuff();
render_stuff();
}
Seperti yang diisyaratkan oleh jawaban lain, sebenarnya tidak ada jawaban yang bagus sesuai spesifikasi. Maksud umum dari
glFlush()
adalah bahwa setelah memanggilnya, CPU host tidak akan memiliki pekerjaan terkait OpenGL yang harus dilakukan - perintah akan didorong ke perangkat keras grafis. Maksud umum dariglFinish()
adalah bahwa setelah ia kembali, tidak ada pekerjaan yang tersisa, dan hasilnya harus tersedia juga semua API non-OpenGL yang sesuai (misalnya membaca dari framebuffer, screenshot, dll ...). Apakah itu benar-benar yang terjadi tergantung pada pengemudi. Spesifikasi memungkinkan banyak kebebasan tentang apa yang legal.sumber
Saya selalu bingung tentang kedua perintah itu juga, tetapi gambar ini menjelaskan semuanya kepada saya: Rupanya beberapa driver GPU tidak mengirim perintah yang dikeluarkan ke perangkat keras kecuali sejumlah perintah telah terakumulasi. Dalam contoh ini angka itu adalah 5 .
Gambar menunjukkan berbagai perintah OpenGL (A, B, C, D, E ...) yang telah dikeluarkan. Seperti yang bisa kita lihat di bagian atas, perintah belum dikeluarkan, karena antrian belum penuh.
Di tengah kita melihat bagaimana
glFlush()
mempengaruhi antrian perintah. Ini memberitahu pengemudi untuk mengirim semua perintah antrian ke perangkat keras (bahkan jika antrian belum penuh). Ini tidak memblokir utas panggilan. Ini hanya memberi sinyal kepada pengemudi bahwa kami mungkin tidak mengirimkan perintah tambahan apa pun. Oleh karena itu menunggu antrian terisi akan membuang-buang waktu.Di bagian bawah kami melihat contoh menggunakan
glFinish()
. Ini hampir melakukan hal yang samaglFlush()
, kecuali bahwa itu membuat utas panggilan menunggu sampai semua perintah telah diproses oleh perangkat keras.Gambar diambil dari buku "Advanced Graphics Programming Using OpenGL".
sumber
glFlush
danglFinish
melakukan, dan saya tidak tahu apa yang dikatakan gambar itu. Ada apa di sisi kiri dan kanan? Selain itu, apakah gambar itu dirilis di Domain Publik atau di bawah beberapa lisensi yang memungkinkan Anda mempostingnya di Internet?Jika Anda tidak melihat perbedaan kinerja apa pun, itu berarti Anda melakukan kesalahan. Seperti yang disebutkan beberapa orang lain, Anda juga tidak perlu memanggil, tetapi jika Anda memanggil glFinish, maka Anda secara otomatis kehilangan paralelisme yang dapat dicapai oleh GPU dan CPU. Biarkan saya menyelami lebih dalam:
Dalam praktiknya, semua pekerjaan yang Anda serahkan ke driver dikelompokkan, dan dikirim ke perangkat keras secara potensial nanti (misalnya pada waktu SwapBuffer).
Jadi, jika Anda memanggil glFinish, pada dasarnya Anda memaksa pengemudi untuk mendorong perintah ke GPU (yang dikumpulkan sampai saat itu, dan tidak pernah meminta GPU untuk bekerja), dan menghentikan CPU sampai perintah yang didorong sepenuhnya dieksekusi. Jadi selama GPU bekerja, CPU tidak (setidaknya di thread ini). Dan sepanjang waktu CPU melakukan tugasnya (kebanyakan perintah batch), GPU tidak melakukan apapun. Jadi ya, glFinish seharusnya merusak kinerja Anda. (Ini adalah perkiraan, karena driver mungkin mulai menjalankan GPU pada beberapa perintah jika banyak di antaranya sudah di-batch. Ini tidak umum, karena buffer perintah cenderung cukup besar untuk menampung cukup banyak perintah).
Sekarang, mengapa Anda memanggil glFinish? Satu-satunya saat saya menggunakannya adalah ketika saya memiliki bug driver. Memang, jika salah satu perintah yang Anda kirimkan ke perangkat keras membuat GPU rusak, maka opsi paling sederhana Anda untuk mengidentifikasi perintah mana yang menjadi penyebabnya adalah dengan memanggil glFinish setelah setiap Draw. Dengan begitu, Anda bisa mempersempit apa yang sebenarnya memicu kecelakaan itu
Sebagai catatan tambahan, API seperti Direct3D tidak mendukung konsep Selesai sama sekali.
sumber
glFlush benar-benar tanggal kembali ke model server klien. Anda mengirim semua perintah gl melalui pipa ke server gl. Pipa itu mungkin menyangga. Sama seperti file atau jaringan apa pun, i / o mungkin buffer. glFlush hanya mengatakan "kirim buffer sekarang, meskipun belum penuh!". Pada sistem lokal, hal ini hampir tidak pernah diperlukan karena OpenGL API lokal tidak mungkin menyangga dirinya sendiri dan hanya mengeluarkan perintah secara langsung. Juga semua perintah yang menyebabkan rendering aktual akan melakukan flush implisit.
glFinish di sisi lain dibuat untuk pengukuran kinerja. Jenis PING ke server GL. Ini melakukan bolak-balik perintah dan menunggu hingga server merespons "Saya menganggur".
Saat ini, pengemudi lokal memiliki ide yang cukup kreatif tentang apa artinya menganggur. Apakah "semua piksel digambar" atau "antrian perintah saya memiliki spasi"? Juga karena banyak program lama menaburkan glFlush dan glFinish di seluruh kodenya tanpa alasan sebagai pengkodean voodoo, banyak driver modern mengabaikannya sebagai "pengoptimalan". Tidak bisa menyalahkan mereka untuk itu, sungguh.
Singkatnya: Perlakukan glFinish dan glFlush sebagai praktik tanpa operasi kecuali Anda membuat kode untuk server OpenGL SGI jarak jauh kuno.
sumber
Lihat di sini . Singkatnya, dikatakan:
Artikel lain menjelaskan perbedaan lain:
glFlush
glFinish
memaksa OpenGL untuk melakukan perintah yang luar biasa, yang merupakan ide yang buruk (misalnya dengan VSync)Singkatnya, ini berarti Anda bahkan tidak memerlukan fungsi-fungsi ini saat menggunakan buffering ganda, kecuali jika implementasi swap-buffer Anda tidak secara otomatis menghapus perintah.
sumber
Sepertinya tidak ada cara untuk menanyakan status buffer. Ada ekstensi Apple ini yang dapat melayani tujuan yang sama, tetapi tampaknya tidak lintas platform (belum mencobanya.) Sekilas, tampaknya sebelum
flush
Anda memasukkan perintah pagar; Anda kemudian dapat menanyakan status pagar tersebut saat berpindah melalui buffer.Saya ingin tahu apakah Anda dapat menggunakan
flush
sebelum melakukan buffering atas perintah, tetapi sebelum mulai membuat frame berikutnya yang Anda panggilfinish
. Ini akan memungkinkan Anda untuk mulai memproses frame berikutnya saat GPU berfungsi, tetapi jika tidak selesai pada saat Anda kembali,finish
akan memblokir untuk memastikan semuanya dalam keadaan baru.Saya belum mencoba ini, tetapi saya akan segera.Saya telah mencobanya pada aplikasi lama yang memiliki penggunaan CPU & GPU yang cukup bagus. (Ini awalnya digunakan
finish
.)Ketika saya mengubahnya menjadi
flush
di akhir danfinish
di awal, tidak ada masalah langsung. (Semuanya tampak baik-baik saja!) Responsivitas program meningkat, mungkin karena CPU tidak berhenti menunggu GPU. Jelas metode yang lebih baik.Sebagai perbandingan, saya menghapus
finished
dari awal bingkai, pergiflush
, dan itu melakukan hal yang sama.Jadi saya akan mengatakan gunakan
flush
danfinish
, karena ketika buffer kosong saat dipanggilfinish
, tidak ada kinerja yang dipukul. Dan saya menebak jika buffernya penuh, Anda pasti menginginkannyafinish
.sumber
Pertanyaannya adalah: apakah Anda ingin kode Anda terus berjalan saat perintah OpenGL dijalankan, atau hanya untuk dijalankan setelah perintah OpenGL Anda dijalankan.
Ini dapat menjadi masalah dalam kasus-kasus, seperti penundaan jaringan, untuk memiliki keluaran konsol tertentu hanya setelah gambar diambil atau semacamnya.
sumber