2 poin oleh GN⁺ 2024-02-15 | 1 komentar | Bagikan ke WhatsApp
  • 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
  • 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
  • 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, last lalu load.i32 result, buffer, idx
  • 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/4 dan load.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
  • 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 ulesel untuk 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

 
GN⁺ 2024-02-15
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

    • Pernyataan bahwa OpenGL lebih mudah daripada Vulkan cukup masuk akal
      Contoh rendering segitiga OpenGL sekitar 200 baris, sedangkan contoh rendering segitiga Vulkan sekitar 1000 baris
    • Secara pribadi, menurut saya Metal cenderung lebih mudah digunakan daripada Vulkan
      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
    • OpenGL bukan dihentikan, melainkan lebih sederhana, dan tetap dipakai di tempat-tempat ketika Vulkan terasa berlebihan
      Jika ia memenuhi semua fungsi yang dibutuhkan dan Anda bisa menerima pipeline rendering berbasis state, menggunakannya untuk proyek baru juga merupakan pilihan yang baik
    • Di macOS dan iOS, OpenGL sudah berstatus akan dihentikan sejak beberapa tahun lalu
      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
    • WGPU lebih dekat sebagai upaya menyelesaikan masalah ini lewat API lintas platform yang lebih mudah digunakan daripada Vulkan
      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

    • Secara lebih umum, OpenGL atau Vulkan yang kompleks bisa dijalankan di atas kombinasi arbitrer antara rendering software CPU dan dukungan akselerasi native spesifik hardware
      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

    • Tidak selalu ada perbedaan besar antara mengimplementasikan fitur lewat kode compute di driver dan mengimplementasikannya lewat dukungan hardware GPU
      “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
    • Cara Alyssa mengungkapkannya terasa agak aneh
      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

    • Pada akhirnya strukturnya adalah membuat command buffer lalu mengirimkannya ke GPU, jadi diperlukan cara untuk melakukan itu di macOS
      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
    • Menurut para pengembang, dalam praktiknya ini sulit karena Apple tidak memiliki API kernel publik yang stabil: https://social.treehouse.systems/@AsahiLinux/111930744188229065
    • Rasanya mungkin saja sudah bisa lewat jalur MoltenVK → Vulkan → Zink
    • Sepertinya Apple melarang driver kernel pihak ketiga
      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
    • Driver OpenGL bisa saja diimplementasikan di atas Metal
      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

    • Dari sudut pandang menulis driver grafis, itu masuk akal, dan juga sesuai dengan Postel's law, yaitu prinsip robustness
      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
    • Tidak adanya pemeriksaan robustness bukan berarti akses di luar batas pasti akan menjadi trap, jadi robustness di sini berarti memberikan hasil yang diketahui bahkan dalam kasus aneh seperti itu
      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
    • Jadi di bidang grafis, komputasi performa tinggi, fisika energi tinggi, dan trading frekuensi sangat tinggi, masa depan C dan C++ masih tetap cerah
      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

    • Lapisan kompatibilitas OpenGL di atas Vulkan bukan sihir
      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
    • Mereka terlebih dahulu menargetkan OpenGL lama agar set fitur dasar bisa berjalan
      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
    • Saya juga sempat berpikir serupa, tetapi untuk mendukung OpenGL di atas Vulkan, bagaimanapun diperlukan versi Vulkan yang lebih tinggi dan beban kerjanya juga besar
      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

    • Quake mungkin hanya bagian kecil dalam sejarah
      Yang pada akhirnya membentuk OpenGL menjadi seperti itu adalah SGI, serta upaya besar untuk membuat implementasi yang kompatibel di berbagai sistem dan arsitektur
    • Fakta menarik: situs OpenGL tertua yang tersimpan memiliki banner besar FAST GAMES GRAPHICS dengan grafis animasi Quake 1 dan menu lain :-P
      https://web.archive.org/web/19970707113513/http://www.opengl.org/
    • Entah apakah itu satu-satunya alasan, tetapi dukungan Carmack terhadap OpenGL jelas membantu
      Banyak hal yang terkait dengan game 3D berkat Doom dan Quake
    • Beberapa tahun kemudian, pada 2011, John Carmack mengatakan bahwa Direct3D saat itu adalah API yang lebih baik
      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/
    • Materi konteks: https://www.chrishecker.com/OpenGL/Press_Release