2 puan yazan GN⁺ 2024-02-15 | 1 yorum | WhatsApp'ta paylaş
  • M1, yıllarca OpenGL 4.1’de takılı kalmıştı; ancak Fedora Asahi Remix’in en yeni M1/M2 sürücüleri OpenGL 4.6 ve OpenGL ES 3.2 için tam destek sunuyor
  • Asahi’nin açık kaynak Linux sürücüsü, üreticinin uyumsuz 4.1 sürücüsünün aksine Khronos listesinde yer alan uygunluk sertifikalı bir sürücü; Blender gibi modern OpenGL iş yükleriyle uyumluluğu genişletiyor
  • OpenGL 4.6; robustness, SPIR-V, clip control, cull distance, compute shaders ve geliştirilmiş transform feedback gerektiriyor, ancak M1 donanımı modern grafik standartlarına doğrudan uymuyor
  • Donanımda bulunmayan özellikler sürücü ve derleyici teknikleriyle tamamlanıyor: geometry shaders, tessellation ve transform feedback compute shaders ile; cull distance ve clip control ise shader dönüşümleriyle işleniyor
  • 100.000’den fazla uygunluk testini geçmek için buffer ve image robustness yazılımda uygulanıyor; clamp, preamble optimizasyonu ve mipmap geçici çözümleriyle ek maliyet azaltılıyor

Fedora Asahi Remix’te OpenGL 4.6/ES 3.2 kullanılabilir

  • M1 şimdiye kadar yalnızca OpenGL 4.1’i destekliyordu; artık OpenGL 4.6 ve OpenGL ES 3.2 destekleniyor
  • En yeni M1/M2 serisi sürücüler Fedora Asahi Remix kurulumu ile kullanılabilir
  • Zaten kurulu olan kullanıcılar aşağıdaki komutla güncelleyebilir
    • dnf upgrade --refresh
  • Asahi’nin açık kaynak Mesa sürücüsü, üreticinin uyumsuz 4.1 sürücüsünün aksine en yeni OpenGL sürümleri için uygunluğa (conformance) sahip
  • Uygun 4.6/3.2 sürücüler, doğruluğu garanti etmek için 100.000’den fazla testi geçmek zorunda
  • Altı ay önce OpenGL ES 3.1 sürücüsüyle M1 için standart grafik API’lerine yönelik ilk uygun sürücünün çıkmasının ardından, bu kez OpenGL 4.6 da tamamlandı
  • Vulkan desteği de geliştirme aşamasında

OpenGL 4.1 engelini aşmak için özelliklerin uygulanması

  • OpenGL 4.6, 4.1’e kıyasla çeşitli zorunlu özellikler ekliyor
    • Robustness
    • SPIR-V
    • Clip control
    • Cull distance
    • Compute shaders
    • Yükseltilmiş transform feedback
  • M1, OpenGL ES 3.1’den daha yeni grafik standartlarına pek iyi uymuyor
    • Vulkan bazı özellikleri isteğe bağlı hale getiriyor; ancak DirectX ve OpenGL’i bunun üzerine katmanlamak için eksik özellikler gerekiyor
    • M1’in mevcut çözümleri OpenGL 4.1 özellik setinin ötesine geçemiyordu
  • Donanım desteği olmayan yeni özellikler sürücü teknikleriyle uygulanıyor
    • Geometry shaders, tessellation ve transform feedback compute shaders ile işleniyor
    • Cull distance, dönüştürülmüş interpolasyon değerleriyle ele alınıyor
    • Clip control, vertex shader epilogue ile uygulanıyor

Buffer robustness ve M1’in yazılım düzeltmesi

  • GPU’lar geleneksel olarak güvenlikten çok performansa öncelik verdiği için, shader’ın buffer sınırının dışını okuduğu hatalı kodlarda tanımsız davranış ortaya çıkabilir
  • Web tarayıcıları gibi güvenilmeyen shader’larla çalışan uygulamalarda bu tür bir ödünleşim istenmez
    • Grafik API’sinin kendisi bir güvenlik sınırı olmadığından bir miktar sanitization gerekir
    • API’deki tanımsız davranışı azaltmak, derinlemesine savunmaya yardımcı olur
  • Robustness etkinleştirildiğinde uygulama, bir miktar performanstan vazgeçerek sınır dışı erişimler için tanımlı davranışı seçebilir
  • API’ye göre sınır dışı buffer load sonuçları farklıdır
    • Direct3D ve Vulkan robustBufferAccess2: 0 döndürür
    • OpenGL ve Vulkan robustBufferAccess: 0 veya buffer içindeki bazı verileri döndürür
    • OpenGL ES: rastgele değer olabilir, ancak çökmez
  • OpenGL gereksinimi, sınır dışı erişimde 0 veya buffer içindeki veriyi döndürmek olduğundan, son geçerli indeks ile erişim indeksinin unsigned minimum değeri hesaplanarak güvenli bir indeksle load yapılabilir
    • robustness olmadan uniform buffer load: load.i32 result, buffer, index
    • robustness uygulandıktan sonra: umin idx, index, last ardından load.i32 result, buffer, idx
  • M1’in preamble yapısı, tüm thread’lerde aynı değeri tekrar tekrar hesaplamak yerine bir kez hesaplayıp yeniden kullanır
    • uniform buffer boyutu sabit olduğundan ek robustness aritmetiği de preamble’a taşınabilir
    • robust storage buffer’da load/store işlemlerinin kendisi taşınamasa bile clamp hesaplaması preamble’a taşınabilir

Vertex buffer robustness uygulaması

  • Grafik API’sinde uygulama, vertex buffer’ın GPU base address’ini ve attribute layout’unu ayarlar
    • Her attribute bir offset ve format içerir
    • Buffer, vertex başına byte sayısını gösteren stride değerine sahiptir
    • Vertex shader, attribute’ları vertex’e göre örtük olarak indeksleyerek okur
  • Bazı donanımlar robust vertex fetch’i native olarak uygular veya bounds-checked buffer ile software fetch’i hızlandırır; ancak M1’de ikisi de yoktur
  • M1 GPU bellek load işlemleri 64 bit base address ve element birimli offset alır; ayrıca imad integer multiply-add komutunu da sunar
    • 32 bit attribute load, imad idx, stride/4, vertex, offset/4 ve load.i32 result, base, idx olmak üzere iki komutla uygulanabilir
    • Yoğun biçimde yerleştirilmiş dört 32 bit değerden oluşan vector attribute, load.v4i32 result, base, vertex << 2 tek komutuyla yüklenebilir
  • Robustness için clamp gerekir; ancak vertex buffer boyutu byte cinsindendir ve optimize edilmiş load, vertex birimli index kullanır
  • Tek bir buffer içindeki birden çok attribute ve offset, attribute başına ayrı base address gibi yeniden yorumlanarak sorun çözülür
    • Offset’i shader’da eklemek yerine attribute başına base aktarılır
    • Byte birimli buffer boyutu, her attribute için vertex birimli boyuta dönüştürülebilir
    • Offset yerine vertex index clamp edilir
  • Sürücü, her attribute formatının boyutunu kullanarak son geçerli vertex index’ini önceden hesaplar ve shader’a aktarır
  • Buffer herhangi bir şey yükleyemeyecek kadar küçükse clamp sorunu çözmez; bu durumda ilgili attribute’un buffer’ı küçük bir zero buffer ile değiştirilir
    • Attribute başına base address kullanıldığı için bu karar da attribute bazında verilebilir
  • Sonuç olarak az miktarda sürücü hesabı ve tek bir umin maliyetiyle robust vertex buffer uygulanır

Image robustness ve mipmap geçici çözümü

  • Buffer robustness dışında image robustness da gerekir; sınır dışı image load 0 döndürmelidir
  • Mipmapped image birden çok level of detail içerir
    • Base level, orijinal görüntüdür
    • Sonraki her level, önceki level’in küçültülmüş görüntüsüdür
    • Render sırasında donanım, verimliliği ve görsel kaliteyi artırmak için ekran boyutuna yakın level’i seçer
  • Spesifikasyon, robustness kapsamında image load’un aşağıdaki durumlarda 0 döndürmesini ister
    • X veya Y koordinatı sınır dışındaysa
    • Level sınır dışındaysa
  • M1 GPU’nun image load davranışı gereksinimlerden farklıdır
    • X veya Y koordinatı sınır dışındaysa 0 döndürür
    • Level sınır dışındaysa son level’in değerini döndürür
  • Üretici donanım dokümantasyonunu yayımlamadığından bu davranışın kasıtlı mı yoksa donanım hatası mı olduğu bilinemez; uygunluğu geçmek için bir geçici çözüm gerekir
  • Basit geçici çözüm, level geçerliyse load yapıp değilse 0 döndüren branch yaklaşımıdır; ancak branch verimsizdir
  • Daha iyi yöntem, sınır dışı level’de bile load’un çökmediği gerçeğinden yararlanarak önce load yapmak ve compare-select ile 0’ı seçmektir
    • Ancak M1 GPU’nun komut seti scalar’dır ve image load red/green/blue/alpha olmak üzere 4 component’li bir vector döndürür
    • Her component için ulesel gerektiğinden assembly büyür
  • Nihai geçici çözüm, X veya Y sınır dışındaysa donanımın 0 döndürmesi gerçeğinden yararlanır
    • Maksimum image genişliği 16384 px olduğundan X’i 20000 gibi bir değere değiştirmek sınır dışına çıkarır
    • Level geçerliyse orijinal X kullanılır; geçerli değilse X 20000’e değiştirilerek image load’un 0 döndürmesi sağlanır
  • Bu yöntem vector’ün tamamını seçmek yerine yalnızca tek bir scalar’ı değiştirdiği için kompakt assembly’ye derlenir
    • Sabit değer uniform register’a önceden alınırsa geçici çözümün maliyeti tek komut olur
    • Bu yöntemle conformance geçilir

1 yorum

 
GN⁺ 2024-02-15
Hacker News yorumları
  • Alyssa Rosenzweig topluluğa katkı yapmayı sürdüren büyük bir nimet gibi görünüyor
    Her blog yazısında modern grafik donanımının iç yapısı hakkında mutlaka daha önce bilmediğim bir şey öğreniyorum

  • Bu çalışma, her seferinde sözden çok becerinin kazandığını gösteriyor
    Sadece blogu okumak bile kafayı alevlendirecek kadar içine girilecek konu sunuyor; üstelik sonuç son cümlede değil ikinci cümlede olsa da, insan yine bit manipülasyonlarını tek tek takip ederek tavşan deliğine giriyor
    Paragraf başına içgörü sayısı diye bir benchmark olsa Alyssa hepsinde birinci olurdu gibi geliyor

  • Bir gün Apple OpenGL 3.3 core desteğini kaldırırsa sonunda herkes de peşinden kaldırabilir
    Genel olarak OpenGL'in Vulkan'dan daha kolay kullanıldığı söyleniyor; aşırı karmaşık API'ler, deneyimi az geliştiricilerin GPU'dan yararlanmasını zorlaştırıp giriş engeli oluşturarak bağımsız oyun geliştiricilerini dışarı itebilir
    Bugünlerde herkes Unity ve Unreal kullanıyor; bu yüzden sıfırdan başlamak ya da başka bir motor kullanmak tuhaf karşılanıyor. Unity daha da kilitlemeye çalıştıktan sonra oyun geliştirmenin bu alanda uyanışını izlemek ilginç ama bir yandan da sinir bozucu
    Oyun geliştirmede açık kaynak hep dardı; Godot var ama Unity ve Unreal'a ciddi biçimde karşı koyması zor görünüyor
    Godot yeterince iyi olsa bile, bağımsız geliştiriciler Unity ve Unreal'a daha alışık olduğu için orada kalmaları muhtemel
    Oyun geliştirmede açık kaynağın durumu bazen umutsuz hissettiriyor ve yeni nesil grafik API'lerinin gelişi işleri kolaylaştırmıyor

    • OpenGL'in Vulkan'dan daha kolay olduğu iddiası epey geçerli
      OpenGL üçgen render etme örneği yaklaşık 200 satırken, Vulkan üçgen render etme örneği yaklaşık 1000 satır
    • Bana kalırsa Metal, Vulkan'dan daha kolay kullanılıyor
      Vulkan çok esnek tasarlanmış ama buna karşılık fazla kolaylık sağlamıyor
      Her iki durumda da OpenGL, sürücünün doğrudan API'si olarak açığa çıkarılmak için fazla yüksek seviyeliydi; temel katmanda Vulkan gibi düşük seviyeli bir API bulundurup onun üstüne OpenGL benzeri bir şey koymak, GPU donanımının çalışma biçimiyle daha iyi örtüşüyor
      Ayrıca herkes Unity ve Unreal da kullanmıyor
      The Game Awards 2023'te yılın oyunu aday gösterilen 6 oyunun tamamı kendi motorlarıyla yapıldı; bağımsız tarafta da Hades gibi kendi motorunu kullanan geliştiriciler hâlâ var
      Yine de çoğunluk için hazır motor kullanmak mantıklı
    • OpenGL kaldırılmış değil; sadece daha basit ve Vulkan'ın gereğinden fazla olduğu yerlerde kullanılmaya devam ediyor
      İhtiyaç duyulan özelliklerin hepsini karşılıyor ve durum tabanlı render pipeline'ını kabul edebiliyorsanız, yeni projelerde kullanmak da gayet iyi bir tercih
    • macOS ve iOS'ta OpenGL zaten birkaç yıldır kullanımdan kaldırılma sürecinde
      Hâlâ çalışıyor ve bugünlerde Metal üzerindeki bir katman aracılığıyla yürütülüyor ama macOS ya da iOS için GL kodu derlerseniz sürekli kullanımdan kaldırma uyarısı alıyorsunuz
      Bunu bir define ile kapatabilirsiniz
    • WGPU, Vulkan'dan daha kolay bir çapraz platform API ile bu sorunu çözmeye çalışan tarafa daha yakın
      OpenGL'in sorunu, GPU'nun çalışma biçiminden fazla uzak olması; bu yüzden yüksek performans elde etmek zor
  • Bu çalışmanın ne kadarının M1 GPU koduna sıkı sıkıya bağlı olduğunu ve ne kadar özellik-üstüne-özellik uygulamasının başka yerlerde de yeniden kullanılabileceğini merak ediyorum
    Zink'in daha ilkel Vulkan üzerinde karmaşık OpenGL özelliklerini çalıştırma biçimine çok benziyor, ama M1 için henüz hedef alınabilecek bir Vulkan backend yok

    • Daha genel olarak, karmaşık OpenGL ya da Vulkan; CPU yazılım render'ı ile donanıma özgü yerel hızlandırma desteğinin rastgele kombinasyonları üzerinde çalıştırılabilir
      Sonuçta mesele iş yükü ve farklı donanımlarda yeniden kullanılabilir
      Eski olduğu için iyi anlaşılmış ama modern iş yüklerinde tek başına kullanılması zor olan donanımlar için de faydalı olabilir
  • Bunun yarattığı performans etkisinin, özellikle macOS'ta, Metal'i doğrudan kullanmaya kıyasla ne düzeyde olduğunu gerçekten merak ediyorum
    Cevap belli ki “duruma göre değişir” olacak ama yine de merak ediyorum
    Yazının içinde yanıtı olabilir ama çoğunu anlayamadım

    • Özellikleri sürücünün compute koduyla uygulamak ile GPU donanım desteğiyle uygulamak arasında mutlaka büyük bir fark olmak zorunda değil
      “Donanım desteği” de çoğu zaman GPU mikrokodu ile uygulanıyor ve çoğu durumda aynı silikon üzerinden geçiyor
      Her özellik performans darboğazı olabilir; gerçekten denemeden önce nerede tıkanacağını bilmek zor
    • Alyssa'nın kullandığı ifade biraz tuhaf geliyor
      Apple GPU'larının geometry shader'ı yerel olarak desteklemediği doğru, ama geometry shader zaten iyi tasarlanmış bir özellik değil ve GPU donanımına da pek uymuyor
      Gerçekten destekleyen donanımlarda bile yavaş olduğu biliniyor; Nvidia'nın mesh shading tasarlamasının bir nedeni var
      Transform feedback de sık anılıyor ama Apple GPU'ları herhangi bir shader aşamasında bellekte rastgele konumlara yazabildiği için transform feedback fiilen gereksiz
      Asıl mesele, Apple'ın sade bir compute mimarisi uygularken eski yükleri ve iyi çalışmadığı bilinen birçok özelliği kesip atmış olması
      “M1, OpenGL 4.1'e sıkıştı” ifadesi pek uygun görünmüyor
      Apple uzun zaman önce OpenGL'i takip etmeyi bıraktığı için 4.1 sonrasında hangi özelliklerden söz edildiğini bilmiyorum; ama OpenGL'de yapılıp Metal'de yapılamayan bir şey varsa buna çok şaşırırım
      Tersi yönde ise, Metal'de mümkün olup OpenGL'de tamamen imkânsız olan çok şey var; buna örnek olarak Metal shading language'deki tam pointer desteği verilebilir
  • Bu, M1’in Fedora sürümü için
    macOS’ta da mümkün hale gelirse şaşırtıcı olurdu; ama bunu yapmak için ne gerektiğini merak ediyorum

    • Sonuçta mesele komut arabellekleri oluşturup bunları GPU’ya gönderen bir yapı, dolayısıyla macOS’ta bunu yapmanın bir yolu gerekli
      M1 GPU için ilk Mesa sürücüsü de macOS’un AGX sürücüsüne IOKit ile komut arabellekleri göndererek bootstrap edilmişti
      https://rosenzweig.io/blog/asahi-gpu-part-2.html
      https://github.com/AsahiLinux/gpu/blob/main/demo/iokit.c
      Bu yüzden GPU’nun surface’ini macOS ekranında birleştirilebilecek bir hedefe aktarmak için Mesa tarafında biraz daha yapıştırıcı kod gerekiyor
    • Geliştiricilere göre Apple’da istikrarlı bir açık çekirdek API’si olmadığı için pratikte zor: https://social.treehouse.systems/@AsahiLinux/111930744188229065
    • Belki zaten MoltenVK → Vulkan → Zink yoluyla mümkün olabilir diye düşünüyorum
    • Apple, üçüncü taraf çekirdek sürücülerini yasaklıyor gibi görünüyor
      Düzgün bir Vulkan ya da OpenGL uygulaması yapmak için GPU işlemlerinden sorumlu çekirdek tarafında bir eş gerektiğini anlıyorum
      Muhtemelen bu yüzden macOS için yerel Vulkan gerçekleştirmeye çalışan kimse yok
      Ama Apple sürücülerinin üstünde mümkünse, ondan emin değilim
    • Metal üzerinde bir OpenGL sürücüsü gerçekleştirilebilir
      Ama optimal olmayan bir legacy API için bu kadar çok kaynak harcamak için bir neden var mı, emin değilim
  • Sınır dışı erişimi trap’ten rastgele veri döndürmeye çevirmeye sağlamlık demeleri epey komik
    Grafik programlama gerçekten tuhaf

    • Grafik sürücüsü yazma açısından mantıklı ve Postel yasasıyla, yani sağlamlık ilkesiyle de uyumlu
      GPU sürücülerinin asıl işi bozuk uygulamaları çalıştırmak ya da onları daha hızlı çalıştırmak
      Varsayılanları katılaştırmak, kırık kod yayınlayan video oyun sektöründeki yapısal sorunu çözmez; sadece kullanıcıları uzaklaştırır
      Dallanmanın genelde çok pahalı olduğu donanımlarda, sistemin sınır durumlarını en verimli şekilde sessizce ele almasını söyleyen bir bayrak kullanışlı görünüyor
      Programcının bu tür sınır durumlarının nihai render karesine neredeyse hiç etkisi olmadığından makul biçimde emin olabileceği birçok geçerli kullanım alanı da vardır muhtemelen
    • Sağlamlık denetimi olmaması, sınır dışı erişimin mutlaka trap’lendiği anlamına gelmiyor; burada sağlamlık, bu garip durumlarda bile bilinen bir sonuç sağlaması demek
      Bu da GPU’ların genel olarak trap’lerden pek hoşlanmamasıyla uyumlu
      Carmack da megatexture tasarlarken üreticilere sanal bellek fikrini kabul ettirmenin acı verici olduğunu söylemişti
    • Bu yüzden grafik, yüksek performanslı hesaplama, yüksek enerji fiziği ve yüksek frekanslı alım satım alanlarında C ve C++ için gelecek hâlâ parlak
      “Performans güvenliğin önündedir” kültürünün egemen olduğu alanlarda başka programlama dillerinden söz etmek, duvara konuşmaya benziyor
  • Kesinlikle çok ilginç bir gelişme, ama neden önce Vulkan hedeflenmediğini merak ediyorum
    Günümüzde daha önemli hedef gibi görünüyor ve onun üzerinde zaten bir OpenGL uygulaması da var

    • Vulkan üzerindeki OpenGL uyumluluk katmanı sihir değil
      Belirli OpenGL özelliklerini desteklemek için Vulkan sürücüsünün bunlara karşılık gelen özellikleri desteklemesi gerekir ve genelde extension gerekir
      Yani sadece temel bir Vulkan sürücüsü gerçekleştirmek size bedavadan OGL 4.6 desteği kazandırmaz; Mesa’nın OGL 4.6’yı Vulkan’a çevirebilmesi için Vulkan sürücüsünde OGL 4.6 özelliklerinin tamamını gerçekleştirmek gerekir
      Üstelik Alyssa daha önce tersine mühendislik ve OpenGL sürücüsü projeleri yapmış biri
      Ayrıntıları bilmiyorum ama alışık olunan bir API için sürücü yazmak, alışık olunmayan bir API için sürücü yazmaktan büyük ihtimalle çok daha kolay ve hızlıdır
    • Önce eski OpenGL hedeflenerek temel özellik seti çalışır hale getirildi
      Buradan daha yeni OpenGL’e çıkmanın, tam bir Vulkan uygulaması yapmaktan daha az iş olması çok muhtemel; ayrıca Vulkan için gereken pek çok şeyi de bu süreçte öğrenmişlerdir
    • Ben de benzer düşündüm, ama OpenGL’i Vulkan üzerinde desteklemek için zaten daha yüksek bir Vulkan sürümü gerekiyor ve iş yükü de büyük
      Bu yüzden daha hızlı çalışan bir şey elde etmek adına önce daha düşük bir OpenGL sürümünü seçmiş gibi görünüyor
  • 90'larda John Carmack Quake II'de OpenGL kullanmakta ısrar etmemiş olsaydı, 3D oyunlarda OpenGL'in bu kadar görünürlük kazanamayabileceğini düşünmek oldukça şaşırtıcı

    • Quake muhtemelen tarihin yalnızca küçük bir parçasıydı
      OpenGL'i sonuçta olduğu şeye dönüştüren, SGI ve birçok sistem ile mimaride uyumlu uygulamalar oluşturmak için verilen devasa çabaydı
    • Eğlenceli bir bilgi olarak, korunmuş en eski OpenGL sitesi; animasyonlu Quake 1 grafiği ve farklı menüleri olan büyük bir FAST GAMES GRAPHICS afişine sahipti :-P
      https://web.archive.org/web/19970707113513/http://www.opengl.org/
    • Bunun tek neden olup olmadığını bilmiyorum ama Carmack'in OpenGL'i desteklemesi kesinlikle yardımcı oldu
      3D oyunlarla ilgili birçok şeyi Doom ve Quake'e borçluyuz
    • Birkaç yıl sonra, 2011'de John Carmack, o dönemde Direct3D'nin daha iyi bir API olduğunu söylemişti
      Microsoft'un API'yi iyileştirmek için büyük uyumsuz değişiklikleri yapmaya devam etme cesaretine sahip olduğunu, OpenGL'in ise uyumluluk kaygıları nedeniyle geri kaldığını düşünüyordu
      Direct3D'nin multithreading'i daha iyi ele aldığını ve modern sürümlerinin durum yönetiminde de daha iyi olduğunu söylemişti
      Yine de id Software'in OpenGL'de kalmasının nedeninin ataletten kaynaklandığını, avantajlarına rağmen Direct3D'ye geçme planları olmadığını söylemişti
      Kaynak: https://www.bit-tech.net/news/gaming/pc/carmack-directx-better-opengl/1/
    • Bağlam materyali: https://www.chrishecker.com/OpenGL/Press_Release