Apa pendekatan yang baik untuk menangani seragam di OpenGL modern?

8

Saya membuat renderer menggunakan OpenGL modern (3.1 dan lebih tinggi) dan sekarang saya mencoba menciptakan cara yang efisien namun fleksibel dalam menangani seragam. Saya telah membaca tentang objek buffer seragam dan tentang apa pendekatan 'umum' untuk menggunakan ini (yang terakhir sayangnya tidak memberi saya hasil sebanyak yang saya harapkan).

Untuk mengurangi panggilan OpenGL API dan menyimpan data dalam memori yang berdekatan, saya sedang mempertimbangkan membuat beberapa buffer besar untuk setiap struktur data yang harus diunggah ke GPU. Setiap buffer memiliki ukuran maksimum 16kb (seperti yang saya pahami, banyak yang dijamin tersedia untuk UBO). Ketika suatu objek ingin dapat mengunggah seragam ke GPU, ia mengambil buffer pertama dari tipe to-be-upload yang belum penuh dan mendapatkan indeks berikutnya yang tersedia di buffer itu. Ketika objek ditarik, ia mengikat UBO (jika belum terikat) dan mengunggah indeks elemen UBO.

Ini menghasilkan sesuatu seperti ini:

layout(std140) uniform ModelData { 
    mat4 model_matrix[kNumInstancesPerModelUbo]; 
}
uniform int u_ModelDataIndex;

layout(std140) uniform SkeletonData { 
    mat4 bone_transforms[kNumInstancesPerSkeletonUbo][kMaxBones]; 
}
uniform int u_SkeletonDataIndex;

Namun saya juga mempertimbangkan yang berikut ini:

layout(std140) uniform MeshData {
    mat4 model_matrix[kNumInstancesPerMeshUbo];
    mat4 bone_transforms[kNumInstancesPerMeshUbo][kMaxBones];
}
uniform int u_MeshDataIndex;

Dalam beberapa hal ini terasa jauh lebih bersih karena dibutuhkan satu indeks untuk mengakses semua data yang terkait dengan mesh yang akan diunggah. Di sisi lain ini bisa keluar dari tangan (ukuran buffer lebih besar dari 16kb, menangani ke data yang tidak relevan (misalnya mesh tanpa kerangka) atau bahkan masalah sinkronisasi karena Anda tidak diizinkan akses untuk mengatakan tulang saat mengunggah matriks model) dan saya tidak yakin bagaimana ini akan mempengaruhi tata letak memori pada GPU juga.

Terus terang rasanya saya terjebak di sini dan saya tidak dapat menemukan contoh nyata yang baik tentang bagaimana Anda akan menangani UBO yang cepat dan fleksibel.

Apakah Anda memiliki saran atau sumber daya untuk saya yang dapat membantu saya di sini?

PhilipMR
sumber

Jawaban:

2

Suballocating dari buffer yang lebih besar benar-benar cara untuk pergi, dengan peringatan. Saya datang lebih banyak dari sisi DirectX / Vulkan, tetapi ini harus berlaku sama untuk OpenGL (Saya hanya tidak akan memiliki panggilan API langsung di sini dalam jawaban ini). Hal-hal yang perlu dipertimbangkan adalah sebagai berikut:

  • Apakah Anda perlu mengindeks ke buffer yang lebih besar, atau apakah Anda baik-baik saja dengan mengikat sumber daya ke offset setiap kali?
  • Sudahkah Anda mengurus semua / semua pembatasan penyelarasan untuk seragam Anda yang dikemas bersama (penyelarasan 256 byte adalah umum)?

API grafik yang lebih baru memiliki "offset dinamis" yang dapat Anda tentukan dengan perintah draw yang merupakan cara yang cukup cepat untuk secara tidak langsung mengakses subregion buffer. Namun, dengan asumsi Anda adalah data triple-buffering yang bisa berubah, harus ada sedikit atau tidak ada pertentangan dalam driver untuk mengikat data (hanya beberapa overhead tetap).

Singkatnya, ya, mengalokasikan wilayah memori / buffer yang lebih besar dan menyewakan wilayah tersebut dianggap praktik terbaik. Ini berlaku bahkan untuk objek dengan shader yang berbeda (jika pengalokasi Anda dapat menanganinya).

jeremyong
sumber
0

Sertakan fase pembandingan untuk kedua solusi di aplikasi Anda dan kemudian pilih solusi yang menang saat runtime. Ini sederhana, portabel, dan bukti masa depan. Maksud saya, Anda memiliki tes untuk ini, kan? ;-)

Saya tahu ini adalah jawaban yang cukup umum untuk "praktik terbaik" untuk kinerja tinggi tetapi jika Anda memikirkannya ada ribuan konfigurasi target yang mungkin dan banyak vendor untuk dipertimbangkan. Jika Anda membutuhkan sedikit tambahan, bayar vendor Anda untuk driver yang dioptimalkan untuk aplikasi Anda.

Andreas
sumber