Mengapa OpenGL> = 3 hanya mengizinkan VBO?

21

Saya melihat bahwa OpenGL versi 3 dan lebih tinggi menghilangkan penggunaan rendering sisi klien. Mode segera telah dihilangkan, dan array vertex tampaknya sudah usang. Sebaliknya, jika saya mengerti dengan benar, VBO adalah cara utama rendering simpul.

Sementara saya melihat logika di balik memiliki cara yang seragam untuk merender semuanya, apakah ini kasus bahwa VBO tidak memiliki kerugian besar atas array vertex? Saya pikir VBO seharusnya adalah buffer besar yang mengandung> 1MB data, secara umum. Bagaimana jika saya memiliki pemandangan yang memiliki banyak geometri yang lebih kecil? Saya memiliki grafik adegan dengan sejumlah besar node, yang masing-masing membutuhkan transformasi sendiri, dll. Setiap node juga harus dapat dihapus secara terpisah, ditambahkan secara terpisah, dll. Saya menggunakan array vertex sebelumnya. Jadi pertanyaan pertama saya adalah apakah, jika saya beralih ke VBO, akan ada overhead yang lebih besar untuk objek grafik adegan saya sekarang karena VBO perlu dialokasikan untuk setiap objek.

Kekhawatiran lain adalah bahwa geometri yang saya render bisa sangat dinamis. Dalam kasus terburuk, mungkin ada saat-saat ketika semua geometri perlu dikirim ulang setiap frame untuk beberapa periode waktu. Akankah VBO memiliki kinerja yang lebih buruk daripada array vertex dalam kasus penggunaan ini, atau apakah VBO paling buruk berfungsi seperti halnya array vertex tetapi tidak lebih?

Jadi, dalam format yang lebih ringkas, pertanyaan saya adalah:

1) Apakah ada overhead yang substansial untuk mengalokasikan / membatalkan alokasi VBO (maksud saya hanya tindakan mendirikan buffer)?

2) Jika saya memperbarui data dari CPU setiap frame, dapatkah ini jauh lebih buruk daripada jika saya menggunakan array vertex?

Dan akhirnya, saya ingin tahu:

3) Jika jawaban untuk salah satu dari pertanyaan di atas adalah "ya", mengapa mencabut mode rendering lain yang dapat memiliki keunggulan dibandingkan VBO? Apakah ada sesuatu yang saya lewatkan di sini, seperti teknik yang seharusnya saya gunakan untuk mengurangi beberapa biaya alokasi potensial ini, dll.?

4) Apakah jawaban untuk semua pertanyaan ini berubah secara substansial tergantung pada versi OpenGL apa yang saya gunakan? Jika saya refactor kode saya menjadi OpenGL 3 atau 4 yang kompatibel dengan maju dengan menggunakan VBO dengan cara yang performan, apakah teknik yang sama akan berfungsi dengan baik dengan OpenGL 2, atau kemungkinan teknik tertentu jauh lebih cepat dengan OpenGL 3 + dan yang lainnya dengan OpenGL 2?

Saya mengajukan pertanyaan ini pada stack overflow, tetapi saya memposting ulang di sini karena saya menyadari situs ini mungkin lebih sesuai untuk pertanyaan saya.

Gravitasi
sumber
1
Mengapa memilih untuk ditutup? Apakah ini dup? Jika demikian, dapatkah saya melihat tautan sehingga saya bisa mendapat manfaat darinya?
Gravity

Jawaban:

23

Apakah ada overhead yang substansial untuk mengalokasikan / membatalkan alokasi VBO (maksud saya hanya tindakan mendirikan buffer)?

Definisikan "substansial." Biasanya bijaksana untuk tidak membuatnya di tengah bingkai; mereka harus diatur selama inisialisasi atau di mana pun. Tapi ini berlaku untuk sebagian besar objek OpenGL, seperti tekstur, renderbuffers, atau shader.

Jika saya memperbarui data dari CPU setiap frame, dapatkah ini jauh lebih buruk daripada jika saya menggunakan array vertex?

Bisa kah? Iya nih. OpenGL mendefinisikan fungsionalitas, bukan kinerja . Anda memang bisa membuat banyak hal lebih lambat. Atau Anda dapat membuat segalanya lebih cepat. Itu semua tergantung pada bagaimana Anda menggunakannya.

Wiki OpenGL memiliki artikel bagus tentang cara mengalirkan data dengan benar .

Jika jawaban untuk salah satu dari pertanyaan di atas adalah "ya", mengapa mencabut mode rendering lain yang dapat memiliki keunggulan dibandingkan VBO? Apakah ada sesuatu yang saya lewatkan di sini, seperti teknik yang seharusnya saya gunakan untuk mengurangi beberapa biaya alokasi potensial ini, dll.?

Pertama, mereka tidak hanya ditinggalkan. Penghentian berarti menandai sesuatu sebagai "akan dihapus" di versi mendatang. Mereka tidak digunakan lagi di 3.0, dan dihapus di 3.1 core ke atas.

Kedua, ARB secara umum menjelaskan alasan mereka menghapus barang dari OpenGL. Itu membuat spec lebih kecil dan lebih sederhana. Itu membuat API lebih kecil dan lebih ramping. Ini membuatnya lebih mudah untuk mengetahui API apa yang seharusnya Anda gunakan; 2.1 memiliki 4 cara untuk menyediakan data titik; 3.1+ memiliki 1. Ini menghilangkan banyak celah. Dll

Apakah jawaban untuk semua pertanyaan ini berubah secara substansial tergantung pada versi OpenGL apa yang saya gunakan? Jika saya refactor kode saya menjadi OpenGL 3 atau 4 yang kompatibel dengan maju dengan menggunakan VBO dengan cara yang performan, apakah teknik yang sama akan berfungsi dengan baik dengan OpenGL 2, atau kemungkinan teknik tertentu jauh lebih cepat dengan OpenGL 3 + dan yang lainnya dengan OpenGL 2?

Kurang lebih tidak. Hanya pada MacOSX perbedaan antara versi 3.1 + inti dan pra-3.0 benar-benar tampak. Profil kompatibilitas diterapkan oleh semua driver untuk Linux dan Windows, sehingga Anda dapat mengasumsikan bahwa profil inti dari driver ini benar-benar hanya menambahkan pemeriksaan untuk mencegah Anda memanggil fungsi kompatibilitas.

Di bawah Mac OSX 10.7, GL 3.2 core tersedia, tetapi bukan profil kompatibilitas. Yang tidak selalu berarti apa-apa bagi kinerja teknik pada satu versus lain. Tetapi itu berarti bahwa jika ada perbedaan, itu adalah platform Anda akan melihatnya.

Nicol Bolas
sumber
1
Karena Anda baru saja mengirim silang pertanyaan ini , saya hanya akan mengirim silang jawaban saya.
Nicol Bolas
Keuntungan lain dari menjaga API tetap ringkas adalah membuat OpenGL API lebih mudah diimplementasikan. Ini adalah pertimbangan besar dalam spesifikasi OpenGL ES asli.
notlesh
@stephelton: Masuk akal. Pertanyaan saya "mengapa mencela segala sesuatu kecuali VBO" didasarkan pada pemikiran bahwa meskipun masuk akal untuk menjaga API tetap ramping, tidak masuk akal untuk mencela semua fitur yang bisa lebih baik daripada VBO untuk banyak kasus penggunaan. Dari apa yang saya dengar, tampaknya tidak ada kerugian untuk menggunakan VBO, jadi sangat masuk akal untuk mencela semua yang lain.
Gravity
@ gravitasi Anda tidak harus menggunakan VBO. Anda dapat menggunakan berbagai simpul juga.
notlesh
18

Cara OpenGL bekerja, kapan pun Anda menggunakan data non-VBO, driver harus membuat salinannya - dalam praktiknya membuat VBO sementara - karena tidak ada yang menghalangi Anda dari memodifikasi ruang kosong array pengguna-ruang Anda antara panggilan ke OpenGL.

Mungkin ada beberapa tipuan sisi pengemudi untuk membuat alokasi temp lebih cepat, tetapi tidak ada yang dapat Anda lakukan untuk menghindari penyalinan.

Jadi ya, selama Anda - dan pengembang driver - melakukan segalanya dengan benar, VBO harus (tm) selalu mempercepat.

Jari Komppa
sumber
6
Saya suka jawaban ini lebih baik. Lebih pendek dan lebih langsung ke intinya, imo.
TravisG
@JariKomppa: Kedengarannya seperti penjelasan yang sangat masuk akal. Saya masih memiliki satu kekhawatiran: VBO seharusnya adalah objek yang cukup besar, sering dialokasikan sebagai buffer 1MB - 4MB terakhir kali saya periksa. Bagaimana jika objek geometri saya tidak terlalu besar, tetapi saya masih khawatir tentang kinerja karena saya memiliki banyak objek? Saya khawatir VBO mungkin hanya untuk kasus penggunaan yang berbeda dari yang saya miliki. Haruskah saya menyatukan beberapa objek dalam satu VBO dan kemudian gunakan glDrawRangeElementsuntuk menggambar masing-masing objek, atau apakah itu tidak efisien seperti array vertex?
Gravity
Saya ragu itu akan membuat perbedaan, tetapi jika Anda merasa itu masalah, patok saja.
Jari Komppa
@JariKomppa: Apa yang Anda ragukan akan membuat perbedaan? Menggunakan glDrawRangeElementsbeberapa kali pada setiap VBO dengan beberapa VBO daripada memberikan masing-masing objek VBO sendiri?
Gravity
1
Persis. Saya ragu Anda akan melihat banyak perbedaan di sana, tetapi membuat profil beberapa kasus uji akan memberi Anda lebih banyak informasi. Saya juga tidak akan khawatir tentang hal itu sekarang, karena perubahan seperti itu dapat diterapkan nanti jika perlu.
Jari Komppa
9

dan array vertex tampaknya sudah usang. Sebaliknya, jika saya mengerti dengan benar,

Tidak terlalu. Array vertex adalah dasar untuk objek buffer verteks. Hanya penyimpanan yang dipindahkan dari klien ke sisi server.

Bagaimana jika saya memiliki pemandangan yang memiliki banyak geometri yang lebih kecil?

Gabungkan set geometri yang lebih kecil menjadi VBO yang lebih besar. Tidak perlu memiliki satu VBO per batch geometri. Anda dapat dengan sempurna menangani subset VBO untuk rendering. Gunakan offset bukan-nol untuk parameter data Pointer ... gl.

2) Jika saya memperbarui data dari CPU setiap frame, dapatkah ini jauh lebih buruk daripada jika saya menggunakan array vertex?

Untuk ini ada flag penggunaan buffer GL_DYNAMIC_DRAW dan GL_STREAM_DRAW.

Jika jawaban untuk salah satu dari pertanyaan di atas adalah "ya", mengapa mencabut mode rendering lain yang dapat memiliki keunggulan dibandingkan VBO?

Karena tidak ada kelebihan. Bagaimanapun, data geometri harus ditransfer ke GPU. Menggunakan array sisi klien biasa masih akan menyebabkan transfer DMA ke GPU, dan mode langsung akan membangun batch untuk ditransfer terlebih dahulu juga.

Sama sekali tidak ada manfaatnya jika tidak menggunakan VBO.

serigala betina
sumber
Jadi kinerja saya umumnya tidak lebih buruk dengan VBO daripada dengan array vertex, tetapi hanya jika saya mengatur mode dengan benar ke GL_STREAM_DRAW?
Gravity
@ Gravity: Memang. Namun mode buffer hanyalah petunjuk tentang penggunaan yang diharapkan, tetapi tentu saja petunjuk itu harus sesuai dengan apa yang akan Anda lakukan. Juga jangan lupa bahwa Anda dapat memetakan buffer ke dalam ruang alamat proses Anda untuk pembaruan (glMapBuffer, glUnmapBuffer).
datenwolf
tapi kemudian buffer tidak bisa di VRAM, kan? Atau apakah masih di VRAM tetapi hanya bisa dialamatkan melalui alamat proses-ruang? Apakah akses acak menjadi murah dengan teknik ini, atau haruskah saya mencoba memperbarui hanya sejumlah kecil rentang yang berdekatan?
Gravity
@ Gravity: buffer dapat dipetakan hanya baca, tulis saja atau baca tulis. Untuk pembaruan Anda hanya akan memilih menulis. Sekarang menjadi penting untuk mengetahui bagaimana OS modern mengelola ruang alamat virtual, yaitu melalui memori halaman. Dalam kasus hanya peta tulis Anda memetakan sepotong memori transfer DMA dan Anda menulis ke kisaran dipetakan akan pergi ke memori GPU lebih atau kurang secara langsung (konten ditulis ke RAM CPU pertama, tetapi kemudian ditransfer ke GPU oleh DMA transfer). Sangat penting bahwa ini adalah jalur yang lebih langsung daripada jika data melewati array sisi klien: Memori proses reguler tidak cocok untuk DMA
datenwolf