Dukungan OpenGL 4.6 Tersertifikasi Kesesuaian di M1
(rosenzweig.io)- M1 selama bertahun-tahun berhenti di OpenGL 4.1, tetapi driver M1/M2 terbaru di Fedora Asahi Remix kini mendukung penuh OpenGL 4.6 dan OpenGL ES 3.2
- Driver Linux open-source Asahi, berbeda dari driver vendor 4.1 yang tidak kompatibel, adalah driver tersertifikasi kesesuaian yang tercantum di daftar Khronos, sehingga memperluas kompatibilitas workload OpenGL modern seperti Blender
- OpenGL 4.6 mensyaratkan robustness, SPIR-V, clip control, cull distance, compute shaders, dan transform feedback yang ditingkatkan, tetapi hardware M1 tidak sepenuhnya cocok begitu saja dengan standar grafis terbaru
- Fitur yang tidak ada di hardware dilengkapi dengan teknik driver dan compiler: geometry shaders, tessellation, dan transform feedback ditangani dengan compute shaders, sedangkan cull distance dan clip control ditangani lewat transformasi shader
- Untuk lolos lebih dari 100.000 uji kesesuaian, robustness buffer dan image diimplementasikan dalam software, sementara biaya tambahan dikurangi lewat clamp, optimisasi preamble, dan bypass mipmap
OpenGL 4.6/ES 3.2 tersedia di Fedora Asahi Remix
- M1 selama ini hanya mendukung hingga OpenGL 4.1, tetapi kini mendukung OpenGL 4.6 dan OpenGL ES 3.2
- Driver terbaru untuk seri M1/M2 dapat digunakan dengan memasang Fedora Asahi Remix
- Pengguna yang sudah memasangnya dapat memperbarui dengan perintah berikut
dnf upgrade --refresh
- Driver Mesa open-source dari Asahi, berbeda dari driver vendor 4.1 yang tidak kompatibel, memiliki kesesuaian (conformance) untuk versi OpenGL terbaru
- Driver 4.6/3.2 yang sesuai harus lolos lebih dari 100.000 pengujian untuk menjamin akurasi
- Daftar resmi Khronos mencakup OpenGL 4.6 dan OpenGL ES 3.2 dari Asahi
- Setelah 6 bulan lalu hadir driver OpenGL ES 3.1 sebagai driver pertama yang sesuai untuk API grafis standar di M1, kali ini OpenGL 4.6 juga telah selesai
- Dukungan Vulkan juga sedang dikerjakan
Implementasi fitur untuk melewati batas OpenGL 4.1
- OpenGL 4.6 menambahkan sejumlah fitur wajib dibandingkan 4.1
- Robustness
- SPIR-V
- Clip control
- Cull distance
- Compute shaders
- Transform feedback yang ditingkatkan
- M1 tidak terlalu cocok dengan standar grafis yang lebih baru daripada OpenGL ES 3.1
- Vulkan menjadikan sebagian fitur opsional, tetapi untuk melapisi DirectX dan OpenGL di atasnya, fitur yang hilang tetap diperlukan
- Solusi M1 yang ada sebelumnya tidak dapat melampaui set fitur OpenGL 4.1
- Fitur baru tanpa dukungan hardware diimplementasikan dengan teknik driver
- Geometry shaders, tessellation, dan transform feedback ditangani dengan compute shaders
- Cull distance ditangani sebagai nilai interpolasi yang ditransformasikan
- Clip control diimplementasikan sebagai epilogue vertex shader
Robustness buffer dan koreksi software di M1
- GPU secara tradisional memprioritaskan performa dibanding keamanan, sehingga kode keliru ketika shader membaca di luar rentang buffer dapat menyebabkan perilaku tak terdefinisi
- Untuk aplikasi yang menangani shader tidak tepercaya, seperti browser web, kompromi seperti ini tidak ideal
- API grafis sendiri bukan batas keamanan, sehingga sebagian sanitization tetap diperlukan
- Mengurangi perilaku tak terdefinisi pada API membantu defense-in-depth
- Saat Robustness diaktifkan, aplikasi dapat memilih perilaku terdefinisi untuk akses di luar rentang dengan mengorbankan sebagian performa
- Hasil load buffer di luar rentang berbeda-beda menurut API
- Direct3D dan Vulkan
robustBufferAccess2: mengembalikan 0 - OpenGL dan Vulkan
robustBufferAccess: mengembalikan 0 atau sebagian data di dalam buffer - OpenGL ES: dapat berupa nilai sembarang, tetapi tidak boleh crash
- Direct3D dan Vulkan
- Karena persyaratan OpenGL adalah mengembalikan 0 atau data di dalam buffer untuk akses di luar rentang, load dapat dilakukan dengan indeks aman melalui perhitungan unsigned minimum antara indeks valid terakhir dan indeks akses
- Load uniform buffer tanpa robustness:
load.i32 result, buffer, index - Setelah robustness diterapkan:
umin idx, index, lastlaluload.i32 result, buffer, idx
- Load uniform buffer tanpa robustness:
- Preamble M1 menghitung satu kali nilai yang sama di semua thread lalu menggunakannya kembali, alih-alih menghitungnya berulang kali di setiap thread
- Ukuran uniform buffer bersifat tetap, sehingga aritmetika tambahan untuk robustness juga dapat dipindahkan ke preamble
- Pada robust storage buffer, meski load/store itu sendiri tidak dapat dipindahkan, perhitungan clamp dapat dipindahkan ke preamble
Implementasi robustness vertex buffer
- Dalam API grafis, aplikasi mengatur GPU base address dan layout attribute untuk vertex buffer
- Setiap attribute memiliki offset dan format
- Buffer memiliki stride yang menunjukkan jumlah byte per vertex
- Vertex shader membaca attribute dengan pengindeksan implisit berdasarkan vertex
- Sebagian hardware mengimplementasikan robust vertex fetch secara native atau mempercepat software fetch dengan buffer yang bounds-checked, tetapi M1 tidak memiliki keduanya
- Load memori GPU M1 menerima base address 64-bit dan offset berbasis elemen, serta menyediakan instruksi integer multiply-add
imad- Load attribute 32-bit dapat diimplementasikan dengan dua instruksi:
imad idx, stride/4, vertex, offset/4danload.i32 result, base, idx - Attribute vector yang berisi empat nilai 32-bit tersusun rapat dapat dimuat dengan satu instruksi:
load.v4i32 result, base, vertex << 2
- Load attribute 32-bit dapat diimplementasikan dengan dua instruksi:
- Robustness memerlukan clamp, tetapi ukuran vertex buffer dinyatakan dalam byte, sementara load yang dioptimalkan menggunakan indeks berbasis vertex
- Masalah ini diselesaikan dengan menafsirkan ulang beberapa attribute dan offset di dalam satu buffer seolah-olah sebagai base address terpisah per attribute
- Alih-alih menambahkan offset di shader, base per attribute diteruskan
- Ukuran buffer dalam byte dapat dikonversi menjadi ukuran berbasis vertex untuk tiap attribute
- Yang di-clamp adalah indeks vertex, bukan offset
- Driver menghitung terlebih dahulu indeks vertex valid terakhir menggunakan ukuran setiap format attribute, lalu meneruskannya ke shader
- Jika buffer terlalu kecil untuk memuat apa pun, clamp tidak dapat menyelesaikannya, sehingga buffer untuk attribute tersebut diganti dengan zero buffer kecil
- Karena menggunakan base address per attribute, keputusan ini juga dapat dilakukan per attribute
- Pada akhirnya, robust vertex buffer diimplementasikan dengan sedikit perhitungan driver dan biaya satu
umin
Robustness image dan bypass mipmap
- Selain robustness buffer, robustness image juga diperlukan, dan image load di luar rentang harus mengembalikan 0
- Image bermipmap mencakup beberapa level of detail
- Base level adalah gambar asli
- Setiap level berikutnya adalah gambar yang diperkecil dari level sebelumnya
- Saat rendering, hardware memilih level yang dekat dengan ukuran layar untuk meningkatkan efisiensi dan kualitas visual
- Spesifikasi mensyaratkan bahwa dalam robustness, image load harus mengembalikan 0 dalam kasus berikut
- Ketika koordinat X atau Y berada di luar rentang
- Ketika level berada di luar rentang
- Perilaku image load pada GPU M1 berbeda dari persyaratan
- Jika koordinat X atau Y berada di luar rentang, ia mengembalikan 0
- Jika level berada di luar rentang, ia mengembalikan nilai dari level terakhir
- Karena vendor tidak memublikasikan dokumentasi hardware, tidak diketahui apakah perilaku ini disengaja atau bug hardware, dan diperlukan bypass agar lolos kesesuaian
- Bypass sederhana adalah pendekatan branch: hanya melakukan load jika level valid, jika tidak mengembalikan 0, tetapi branch tidak efisien
- Cara yang lebih baik adalah memanfaatkan fakta bahwa load tidak crash meski level di luar rentang: lakukan load terlebih dahulu, lalu pilih 0 dengan compare-select
- Namun instruction set GPU M1 bersifat scalar, sementara image load mengembalikan vector dengan 4 component red/green/blue/alpha
- Diperlukan
uleseluntuk tiap component, sehingga assembly menjadi besar
- Bypass akhir memanfaatkan fakta bahwa hardware mengembalikan 0 jika X atau Y di luar rentang
- Karena lebar maksimum image adalah 16384px, mengubah X menjadi nilai seperti 20000 membuatnya berada di luar rentang
- Jika level valid, gunakan X asli; jika tidak valid, ubah X menjadi 20000 agar image load mengembalikan 0
- Cara ini hanya mengubah satu scalar, bukan memilih seluruh vector, sehingga dikompilasi menjadi assembly yang compact
- Jika konstanta dinaikkan terlebih dahulu ke uniform register, biaya bypass menjadi satu instruksi saja
- Dengan cara ini, conformance berhasil dilalui
1 komentar
Komentar Hacker News
Alyssa Rosenzweig terasa seperti hadiah besar yang terus berkontribusi untuk komunitas
Di setiap posting blognya, saya pasti belajar sesuatu yang sebelumnya tidak saya ketahui tentang struktur internal hardware grafis modern
Ini adalah karya yang menunjukkan bahwa kemampuan nyata selalu mengalahkan kata-kata
Membaca blognya saja sudah membuat kepala panas karena ada begitu banyak hal untuk diurai, dan meski kesimpulannya ada di kalimat kedua, bukan kalimat terakhir, pada akhirnya kita tetap terseret masuk ke lubang kelinci untuk mengikuti setiap manipulasi bit satu per satu
Kalau ada benchmark seperti jumlah pencerahan per paragraf, rasanya Alyssa akan menempati peringkat pertama semuanya
Suatu hari nanti, jika Apple menghentikan OpenGL 3.3 core, mungkin pada akhirnya semua orang juga akan ikut menghentikannya
Secara umum saya dengar OpenGL lebih mudah digunakan daripada Vulkan, tetapi API yang terlalu kompleks bisa membuat developer yang kurang berpengalaman sulit memanfaatkan GPU, menjadi penghalang masuk, dan menyingkirkan developer game indie
Sekarang semua orang memakai Unity dan Unreal, jadi membuat dari nol atau memakai engine lain terlihat aneh; melihat dunia pengembangan game mulai tersadar setelah Unity mencoba lebih mengunci memang menarik, tetapi juga menjengkelkan
Open source dalam pengembangan game selalu serba pas-pasan, dan meski ada Godot, tampaknya sulit untuk benar-benar menantang Unity dan Unreal
Kalaupun Godot sebenarnya cukup mampu, developer indie kemungkinan besar akan tetap bertahan karena mereka lebih terbiasa dengan Unity dan Unreal
Kondisi open source dalam pengembangan game kadang terasa putus asa, dan kemunculan API grafis generasi berikutnya tidak membuat segalanya lebih mudah
Contoh rendering segitiga OpenGL sekitar 200 baris, sedangkan contoh rendering segitiga Vulkan sekitar 1000 baris
Vulkan dirancang sangat fleksibel, tetapi tidak memiliki banyak fitur kemudahan
Bagaimanapun, OpenGL terlalu high-level untuk diekspos sebagai API langsung driver, dan pendekatan dengan API low-level seperti Vulkan sebagai lapisan dasar lalu menaruh sesuatu seperti OpenGL di atasnya lebih cocok dengan cara kerja hardware GPU
Selain itu, tidak semua orang memakai Unity dan Unreal
Keenam nominasi Game of the Year di The Game Awards 2023 semuanya dibuat dengan engine buatan sendiri, dan bahkan di ranah indie masih ada developer seperti Hades yang membuat engine sendiri
Meski begitu, memang benar mayoritas memakai engine siap pakai
Jika ia memenuhi semua fungsi yang dibutuhkan dan Anda bisa menerima pipeline rendering berbasis state, menggunakannya untuk proyek baru juga merupakan pilihan yang baik
Masih berjalan, dan belakangan dijalankan sebagai lapisan di atas Metal, tetapi jika membangun kode GL untuk macOS atau iOS, peringatan deprecation terus muncul
Bisa dimatikan dengan define
Masalah OpenGL adalah ia terlalu jauh dari cara kerja GPU, sehingga sulit menghasilkan performa yang baik
Saya penasaran seberapa banyak dari pekerjaan ini yang terikat pada kode GPU M1, dan seberapa banyak implementasi fitur-di-atas-fitur yang bisa dipakai ulang di tempat lain
Ini terlihat sangat mirip dengan cara Zink menjalankan fitur OpenGL yang kompleks di atas Vulkan yang lebih primitif, tetapi M1 belum punya backend Vulkan untuk dijadikan target
Pada akhirnya ini soal jumlah pekerjaan, dan bisa digunakan ulang untuk berbagai hardware
Ini juga bisa membantu hardware lama yang sudah dipahami dengan baik, tetapi sulit dipakai sendiri untuk workload modern
Saya sangat penasaran seberapa besar dampak performa dari hal ini, terutama dibandingkan memakai Metal langsung di macOS
Jawabannya pasti “tergantung situasi”, tetapi tetap saja penasaran
Mungkin jawabannya ada di artikel, tetapi sebagian besar tidak saya pahami
“Dukungan hardware” juga biasanya diimplementasikan sebagai mikrokode GPU dan sering kali melewati silikon yang sama
Fitur apa pun bisa menjadi bottleneck performa, dan sebelum benar-benar dicoba, sulit mengetahui bagian mana yang akan tersendat
Memang benar Apple GPU tidak mendukung geometry shader secara native, tetapi geometry shader memiliki desain yang kurang baik dan tidak cocok dengan hardware GPU
Bahkan pada hardware yang dikatakan mendukungnya, fitur itu dikenal lambat, dan ada alasan Nvidia merancang mesh shading
Transform feedback juga sering disebut, tetapi Apple GPU dapat menulis ke lokasi memori arbitrer dari tahap shader mana pun, sehingga transform feedback pada dasarnya tidak diperlukan
Intinya adalah Apple menerapkan arsitektur compute yang ringkas sambil memangkas banyak peninggalan lama dan fitur yang diketahui tidak bekerja dengan baik
Ungkapan “M1 terjebak di OpenGL 4.1” tampaknya kurang tepat
Saya sudah lama tidak mengikuti OpenGL, jadi tidak tahu fitur setelah 4.1 mana yang dimaksud, tetapi saya akan sangat terkejut jika ada fitur yang bisa dilakukan di OpenGL tetapi tidak bisa di Metal
Sebaliknya, ada banyak hal yang bisa dilakukan di Metal tetapi sama sekali tidak mungkin di OpenGL, dan fakta bahwa Metal Shading Language memiliki pointer penuh adalah salah satu contohnya
Ini untuk Fedora di M1
Akan mengejutkan kalau ini juga bisa dilakukan di macOS, dan saya penasaran apa saja yang diperlukan untuk membuat hal seperti itu
Driver Mesa awal untuk GPU M1 juga di-bootstrap dengan cara mengirim command buffer ke driver AGX macOS melalui IOKit
https://rosenzweig.io/blog/asahi-gpu-part-2.html
https://github.com/AsahiLinux/gpu/blob/main/demo/iokit.c
Jadi masih diperlukan sedikit kode perekat di sisi Mesa untuk meneruskan surface GPU sebagai target yang bisa dikomposisikan ke layar macOS
Pemahaman saya, untuk membuat implementasi Vulkan atau OpenGL yang layak diperlukan pasangan di sisi kernel yang menangani pemrosesan GPU
Mungkin itu sebabnya tidak ada orang yang mencoba mengimplementasikan Vulkan native untuk macOS
Namun saya tidak yakin kalau itu bisa dilakukan di atas driver Apple
Tapi saya tidak tahu apakah ada alasan untuk menghabiskan begitu banyak resource demi API legacy yang tidak optimal
Cukup lucu menyebut perubahan dari akses di luar batas yang menjadi trap ke pengembalian data arbitrer sebagai robustness
Pemrograman grafis memang aneh
Inti pekerjaan driver GPU adalah menjalankan aplikasi yang rusak atau membuatnya berjalan lebih cepat
Menjadikan default lebih ketat tidak akan memperbaiki masalah struktural industri video game yang merilis kode rusak; yang ada hanya membuat pengguna pergi
Pada hardware yang branching umumnya sangat mahal, flag yang memberi tahu sistem agar menangani edge case secara diam-diam dengan cara paling efisien tampaknya berguna
Sepertinya juga ada banyak kasus penggunaan valid ketika programmer bisa cukup yakin bahwa edge case semacam itu hampir tidak memengaruhi frame render akhir
Jika digabung dengan fakta bahwa GPU secara umum tidak terlalu menyukai trap, ini jadi masuk akal
Carmack juga pernah mengatakan bahwa saat merancang megatexture, membuat para produsen menerima ide memori virtual itu menyakitkan
Membicarakan bahasa pemrograman lain di bidang yang didominasi budaya “performa lebih diutamakan daripada keselamatan” terasa seperti berbicara kepada tembok
Jelas ini sangat menarik, tetapi saya penasaran mengapa mereka tidak menargetkan Vulkan terlebih dahulu
Sekarang Vulkan tampak seperti target yang lebih penting, dan di atasnya juga sudah ada implementasi OpenGL
Untuk mendukung fitur OpenGL tertentu, driver Vulkan harus mendukung fitur padanannya, dan biasanya diperlukan extension
Dengan kata lain, sekadar mengimplementasikan driver Vulkan dasar tidak otomatis memberikan dukungan OGL 4.6 secara gratis; agar Mesa bisa menerjemahkan OGL 4.6 ke Vulkan, driver Vulkan harus mengimplementasikan semua fitur OGL 4.6
Selain itu, Alyssa sudah pernah mengerjakan proyek reverse engineering dan driver OpenGL
Saya tidak tahu detail situasinya, tetapi kemungkinan besar membuat driver untuk API yang sudah familier jauh lebih mudah dan cepat daripada membuat driver untuk API yang belum familier
Dari situ, menaikkannya ke OpenGL yang lebih baru kemungkinan besar merupakan pekerjaan yang lebih sedikit dibanding implementasi Vulkan penuh, dan mereka juga tampaknya banyak belajar tentang hal-hal yang diperlukan untuk Vulkan
Jadi sepertinya mereka memilih versi OpenGL yang lebih rendah terlebih dahulu agar bisa mendapatkan sesuatu yang berjalan lebih cepat
Cukup mengejutkan jika membayangkan bahwa jika pada era 90-an John Carmack tidak begitu bersikeras memakai OpenGL di Quake II, OpenGL mungkin tidak akan punya kehadiran yang berarti dalam game 3D
Yang pada akhirnya membentuk OpenGL menjadi seperti itu adalah SGI, serta upaya besar untuk membuat implementasi yang kompatibel di berbagai sistem dan arsitektur
https://web.archive.org/web/19970707113513/http://www.opengl.org/
Banyak hal yang terkait dengan game 3D berkat Doom dan Quake
Ia menilai Microsoft punya keberanian untuk terus melakukan perubahan besar yang tidak kompatibel demi memperbaiki API, sementara OpenGL terhambat oleh kekhawatiran soal kompatibilitas
Ia mengatakan Direct3D menangani multithreading dengan lebih baik, dan versi terbarunya juga memiliki manajemen state yang lebih baik
Meski begitu, ia mengatakan id Software tetap bertahan di OpenGL karena inersia, dan meskipun ada keunggulan tersebut, tidak ada rencana untuk pindah ke Direct3D
Sumber: https://www.bit-tech.net/news/gaming/pc/carmack-directx-better-opengl/1/