Vulkan: Seragam Buffer versus Push Konstanta untuk data statis

8

Saya agak berjuang untuk memahami perbedaan konseptual antara buffer seragam dan konstanta dorong. Dari apa yang saya dapat kumpulkan dengan membaca spec, perbedaan utamanya adalah:

  1. Buffer yang seragam bisa jauh lebih besar daripada konstanta dorong.
  2. UBO menggunakan std140, PC menggunakan std430.
  3. UBO dapat diperbarui kapan saja dengan vkCmdUpdateBuffer (atau pemetaan host) dan tetap mempertahankan nilainya, PC harus didorong kembali untuk setiap render pass. (Yang mengejutkan saya - berdasarkan namanya. Saya pikir saya benar-benar akan memperbarui konstanta di saluran pipa di tempat, dan perubahan itu tetap ada)

Dalam skenario saya, saya memiliki sekitar ~ 200 byte data yang saya harapkan sebagian besar konstan . Artinya, saya akan jarang mengubahnya. Akankah lebih baik (dengan asumsi ukuran memungkinkan) menggunakan konstanta dorong meskipun saya harus mengirimnya kembali di setiap buffer perintah? Atau lebih baik menggunakan UBO 200-byte dan jarang memperbaruinya dengan vkCmdUpdatebuffer?

Juga. bagaimana jika saya memiliki mis a float random_seedyang akan saya perbarui setiap kali shader dijalankan? Dengan asumsi saya sudah memiliki UBO, apakah akan lebih baik untuk menyamakannya dengan UBO, meskipun sisa UBO konstan, atau apakah saya akan mendapat manfaat dengan menggunakan konstanta dorong untuk variabel ini secara khusus, sehingga saya dapat menghindari keharusan untuk vkCmdUpdateBuffer sebelum setiap render lulus?

haasn
sumber
Selamat datang di situs Computer Graphics Stack Exchange! Saya tidak terbiasa dengan Vulkan tetapi tampaknya menggunakan UBO akan lebih efisien dalam kasus Anda (Anda dapat mencoba membandingkan kinerja kedua pendekatan dalam program sampel). API grafik apa yang Anda kenal? Anda juga mungkin tertarik dengan presentasi GDC 2012 ini: Jangan Buang semuanya: Manajemen Buffer Efisien
hapus
Dari dokumentasi Vulkan : ketika UBO mengalokasikan satu blok memori video pada GPU (yang dapat Anda perbarui pada waktu berikutnya), Constant Constant tidak menggunakan memori video (itulah sebabnya mengapa itu harus disediakan selama setiap panggilan draw / compute call, atau shader tidak akan tahu nilai yang digunakan). Saya kira itu disimpan dalam area penyimpanan jangka pendek dan cepat lainnya pada GPU, meskipun detailnya mungkin tergantung pada vendor GPU Anda.
hapus

Jawaban:

8

UBO dapat diperbarui kapan saja dengan vkCmdUpdateBuffer

Dari spesifikasi: "vkCmdUpdateBuffer hanya diperbolehkan di luar render pass." Jadi "kapan saja" bukan itu masalahnya.

Bahkan jika diizinkan di dalam render pass, itu masih merupakan operasi transfer. Yang berarti Anda perlu menyinkronkan transfer memori dengan perintah yang menggunakannya. Yang memperlambat kinerja.

Untuk hal umum Push Constant vs Uniform, gunakan penilaian Anda. Dengan "penilaian", maksud saya hanya melihat bagaimana mereka bekerja. Push Constants memungkinkan Anda mengubah data mereka kapan saja tanpa melakukan proses yang berat seperti operasi memori, sinkronisasi, atau mengubah status deskriptor. Jelas, itu untuk sering mengubah data. Seberapa sering "sering"? Ya, itu panggilan penilaian.

Gagal itu, profil perbedaan kinerja.

Nicol Bolas
sumber
2

Saya memiliki sekitar ~ 200 byte data yang saya harapkan sebagian besar konstan. Artinya, saya akan jarang mengubahnya.

Jika data berubah jarang, Anda dapat menggunakan Konstanta Spesialisasi . Mereka ditetapkan ketika pipa dibuat, dan pipa baru harus dibuat jika Anda perlu mengubah nilai-nilai. Untuk acara yang jarang terjadi, seperti ukuran jendela, ini mungkin merupakan biaya yang dapat diterima.

bagaimana jika saya memiliki misalnya random_seed float yang akan saya perbarui setiap kali shader dijalankan?

Itu kasus penggunaan yang sempurna untuk Push Constant. Anda dapat menyimpan semua data lainnya di UBO (atau di Konstanta Spesialisasi) dan mengubah nilai ini dengan VkCmdPushConstants.

vazgriz
sumber