Menggunakan instancing untuk semuanya?


16

Instancing meningkatkan kinerja (secara signifikan) ketika merender banyak (hunders? Ribuan?) Salinan dari jala yang sama sekaligus. Tetapi berapa banyak overhead yang dimilikinya ketika merender tepat satu salinan dengan satu panggilan draw? Apakah ide yang baik atau buruk menggunakan instancing untuk semua geometri yang dihasilkan oleh mesin?

Sunting: Katakanlah kita sedang membuat game FPS. Sebagian besar benda hanya memiliki satu contoh: pisau, pistol, senapan mesin, bangunan dan menara radio. Tetapi ada juga beberapa objek dengan banyak contoh: pohon (misalnya 3 jenis pohon dengan ratusan contoh), rumput dan sebagainya ... Yang saya maksudkan adalah: alih-alih memberikan objek satu arah dengan cara "tradisional" dan pohon dan rumput menggunakan instancing, kami membuat semuanya menggunakan instancing. Jadi menara radio kami hanya memiliki satu instance (yang informasinya kami simpan dalam buffer data instan) dan kami membuat menara itu menggunakan semacam DrawInstanced()panggilan dengan jumlah instance sama 1. Sama dengan semua objek lain (tentu saja, pohon dan rumput memiliki banyak instance).

Jadi pertanyaan saya adalah: apakah ide yang buruk untuk menggambar satu instance dari objek menggunakan instancing? Apakah instancing memiliki overhead yang terlalu banyak (berdasarkan ingatan dan kinerja) atau apakah dengan cara apa pun tidak diinginkan untuk me-render objek instance tunggal?

Jawaban:


19

Di bawah D3D9 dengan XPDM Anda hampir pasti ingin membuat instance sedapat mungkin. Overhead panggilan draw begitu tinggi sehingga masuk akal. Dalam skenario itu titik crossover bisa serendah 2 atau 3 contoh.

Jika Anda hanya memiliki satu instance dari mesh yang diberikan, mungkin pada permukaannya tampak menggoda untuk menggambarnya tanpa instances. Namun, lihat apa yang terlibat:

  • Anda perlu beralih dari memuat data ke buffer per instance ke mengunggah konstanta shader.
  • Anda perlu menyimpan dua salinan vertex shader Anda: satu untuk yang dipasang dan satu untuk yang tidak dipasang.
  • Anda perlu menyimpan dua salinan kode rendering Anda: juga.
  • Anda perlu mengganti shader.
  • Anda perlu mengganti format vertex.
  • Anda mungkin perlu mengganti buffer vertex.
  • Dan kemudian Anda perlu mengulanginya lagi jika Anda akan kembali menggambar gambar untuk kelompok jerat berikutnya.

Sekalipun Anda hanya memiliki jaring tunggal (seperti model senjata di FPS) ada beberapa kasus di mana instancing berguna. Katakanlah Anda sedang melakukan akumulasi cahaya multipass di renderer maju dan dengan z-prepass. Alih-alih lulus ekstra untuk setiap cahaya, Anda membuat lampu Anda per-instance data dan Anda menggambar itu dipasang.

Berdasarkan skenario pertama, moral cerita adalah bahwa jika ada kelas objek yang dapat menggunakan instancing sama sekali, masuk akal untuk selalu menggunakan instancing untuk semua objek dari kelas itu.

Berdasarkan skenario kedua, moral dari cerita ini adalah bahwa instancing dapat memiliki kegunaan yang tidak jelas yang melampaui hanya mengatakan "Saya perlu menggambar 20 pohon".


Alasan yang Anda berikan adalah alasan yang sama yang membuat saya mengajukan pertanyaan ini sejak awal. Terima kasih.
NPS

12

(Pada sistem saya, tidak mengujinya di tempat lain) Di GL, memasang jala tunggal (menggambar dengan jumlah = 1) memiliki beberapa overhead yang buruk, tapi saya tidak tahu dari mana asalnya. Saya sangat menyarankan untuk tidak melakukannya.

Saya menguji ini dalam aplikasi praktis beberapa bulan yang lalu. Saya mengkodekan beberapa algoritma penerangan global dalam adegan Crytek Sponza, yang terdiri dari kira-kira 350 atau lebih jerat (tidak ingat persis), di mana pasangan berbagi beberapa contoh. Pada awalnya saya melakukannya seperti yang Anda sarankan, contoh saja semuanya dan menggambar sisanya dengan jumlah contoh 1, karena sedikit menyederhanakan kode rendering.

Kemudian ketika mengoptimalkan penyaji, hanya beralih dari memunculkan jumlah = 1 objek untuk mengirimkannya dengan cara biasa menyelamatkan saya sekitar 3,5 milidetik per frame senilai waktu pada i7 3770k (dan GTX 770). Mengalihkan jerat dengan banyak contoh untuk hanya melakukannya dengan cara tradisional menyelamatkan saya 0,5 ms. Secara keseluruhan aplikasi berubah dari ~ 120 FPS menjadi sekitar ~ 230 FPS.

Angka-angka ini tentu saja selalu tergantung pada di mana hambatan dalam aplikasi Anda, dan 0,5ms yang terakhir mungkin benar-benar menjadi lambat dalam aplikasi di mana Anda sangat terikat panggilan-draw. Tetapi sebaliknya, dalam pengalaman saya, instancing memiliki overhead yang buruk jika Anda tidak menggambar banyak hal sekaligus.


Menarik, tetapi akan menyenangkan untuk melihat data untuk driver AMD dan Intel juga, jika tidak, Anda benar-benar harus mengatakan "Pada sistem saya" bukannya "Dalam GL". Di sisi lain, bahkan jika itu bukan masalah dengan implementasi lain, fakta bahwa itu bisa ada pada beberapa alasan cukup untuk menghindari instance jika Anda tidak menggunakannya.
bcrist

2

Anda dapat yakin bahwa menggambar objek tunggal yang dipasang lebih mahal daripada menggambar objek tunggal secara normal. Untuk pemasangan GPU sedang mempersiapkan sejumlah besar objek dan persiapan ini akan berbeda dari satu objek. Namun seberapa besar kesenjangan kinerja ini hanya dapat ditemukan dengan bereksperimen dan sangat tergantung pada pengaturan rendering aktual Anda. Satu-satunya cara untuk mengetahui dengan pasti adalah dengan mengujinya sendiri. Mematok panggilan undian tunggal sulit di sini adalah beberapa ide tentang bagaimana Anda dapat melanjutkan.


2

Sudah 4 tahun ... dan saya pikir aman untuk mengatakan bahwa tidak apa-apa untuk mengirim panggilan "instances" dengan 1. Seperti yang mungkin Anda perhatikan, API baru DX12 dan Vk keduanya memiliki jumlah instance yang dapat dari 0 hingga NUM_INSTANCES . Perhatikan juga bahwa tidak ada DrawIndexed (...) .

EDIT

Sebagai peringatan, hal di atas mungkin baik-baik saja dengan API modern ini, mungkin menggunakan sesuatu yang lama seperti Gl <3.3 atau mungkin DX11 akan memerlukan profil seperti yang disebutkan oleh pengguna lain.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.