Panduan Desain Vulkan

Tidak seperti API grafis sebelumnya, pada Vulkan, driver tidak melakukan pengoptimalan tertentu untuk aplikasi, seperti penggunaan kembali pipeline. Sebagai gantinya, aplikasi yang menggunakan Vulkan harus mengimplementasikan sendiri pengoptimalan tersebut. Jika tidak, aplikasi dapat berperforma lebih buruk dibandingkan aplikasi yang menjalankan OpenGL ES.

Saat mengimplementasikan sendiri pengoptimalan tersebut, aplikasi berpeluang untuk melakukannya dengan lebih sukses daripada yang dapat dilakukan oleh driver, karena aplikasi memiliki akses ke informasi yang lebih spesifik untuk kasus penggunaan tertentu. Hasilnya, pengoptimalan aplikasi yang menggunakan Vulkan secara cerdas dapat menghasilkan performa yang lebih baik dibandingkan jika aplikasi tersebut menggunakan OpenGL ES.

Halaman ini memperkenalkan beberapa pengoptimalan yang dapat diimplementasikan oleh aplikasi Android Anda untuk mendapatkan peningkatan performa dari Vulkan.

Menerapkan Rotasi Tampilan Selama Rendering

Jika arah hadap-atas aplikasi tidak cocok dengan orientasi tampilan perangkat, compositor akan memutar gambar swapchain aplikasi agar cocok. Compositor melakukan rotasi ini saat menampilkan gambar, yang mengakibatkan konsumsi daya yang lebih tinggi—terkadang jauh lebih tinggi—dibandingkan jika gambar tidak diputar.

Sebaliknya, memutar gambar swapchain saat membuat gambar tersebut akan mengakibatkan sedikit tambahan konsumsi daya, jika ada. Kolom VkSurfaceCapabilitiesKHR::currentTransform menunjukkan rotasi yang diterapkan oleh compositor pada jendela. Setelah aplikasi menerapkan rotasi tersebut selama rendering, aplikasi akan menggunakan kolom VkSwapchainCreateInfoKHR::preTransform untuk melaporkan bahwa rotasi selesai.

Meminimalkan Render Pass Per Bingkai

Pada sebagian besar arsitektur GPU seluler, memulai dan mengakhiri render pass merupakan operasi yang mahal. Aplikasi Anda dapat meningkatkan performa dengan menyusun operasi rendering menjadi sesedikit mungkin render pass.

Operasi attachment-load dan attachment-store yang berbeda menawarkan tingkat performa yang berbeda pula. Misalnya, jika tidak perlu mempertahankan konten lampiran, Anda dapat menggunakan VK_ATTACHMENT_LOAD_OP_CLEAR atau VK_ATTACHMENT_LOAD_OP_DONT_CARE yang lebih cepat, bukan VK_ATTACHMENT_LOAD_OP_LOAD. Demikian pula, jika tidak perlu menulis nilai akhir lampiran ke memori untuk digunakan nanti, Anda dapat menggunakan VK_ATTACHMENT_STORE_OP_DONT_CARE untuk mendapatkan performa yang jauh lebih baik daripada VK_ATTACHMENT_STORE_OP_STORE.

Selain itu, pada hampir semua render pass, aplikasi Anda tidak perlu memuat atau menyimpan lampiran kedalaman/stensil. Dalam kasus semacam ini, Anda dapat menghindari keharusan mengalokasikan memori fisik untuk lampiran dengan menggunakan tanda VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT saat membuat gambar lampiran. Bit ini memberikan manfaat yang sama seperti glFramebufferDiscard pada OpenGL ES.

Memilih Jenis Memori yang Sesuai

Saat mengalokasikan memori perangkat, aplikasi harus memilih jenis memori. Jenis memori menentukan cara aplikasi menggunakan memori, dan juga menjelaskan properti caching dan koherensi memori. Perangkat yang berbeda memiliki jenis memori yang berbeda; jenis memori yang berbeda menunjukkan karakteristik performa yang berbeda.

Aplikasi dapat menggunakan algoritme sederhana untuk memilih jenis memori terbaik untuk penggunaan tertentu. Algoritme ini memilih jenis memori pertama dalam array VkPhysicalDeviceMemoryProperties::memoryTypes yang memenuhi dua kriteria: Jenis memori tersebut harus diizinkan untuk buffer atau gambar, dan harus memiliki properti minimum yang diperlukan aplikasi.

Secara umum, sistem seluler tidak memiliki heap memori fisik terpisah untuk CPU dan GPU. Pada sistem semacam ini, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT tidak se-signifikan seperti pada sistem yang memiliki GPU tersendiri dengan memori khususnya sendiri. Aplikasi tidak boleh berasumsi properti ini bersifat wajib.

Mengelompokkan Set Deskriptor menurut Frekuensi

Jika Anda memiliki binding resource yang berubah pada frekuensi yang berbeda-beda, gunakan beberapa set deskriptor per pipeline, bukan mem-binding ulang semua resource untuk setiap draw. Misalnya, Anda dapat memiliki satu set deskriptor untuk binding per-scene, set lainnya untuk binding per-material, dan set ketiga untuk binding instance per-mesh.

Gunakan konstanta langsung untuk perubahan dengan frekuensi tertinggi, seperti perubahan yang dijalankan dengan setiap panggilan draw.