- Mach engine’in deneysel grafik API’si sysgpu, Direct3D 12 için shader çıktıları gerektiriyordu; bu yüzden Microsoft DXC, statik ve çapraz platformda kullanımı kolay bir biçimde yeniden derlendi
- Direct3D 12’nin DXIL’i, Microsoft’un LLVM/Clang 3.7 fork’unun ürettiği sonradan işlenmiş LLVM bitcode’a yakın; bu nedenle yapı, spesifikasyondan çok “gerçek derleyici çıktısına” dayanıyor
- WebGPU ailesi runtime’ları genelde WGSL’i HLSL’e dönüştürüp ardından FXC veya DXC ile DXBC/DXIL üretir; ancak DXC dağıtım yükü nedeniyle eski ve yavaş FXC kolayca varsayılan seçenek hâline gelir
- Mevcut DXC’yi statik linklemek zordur;
dxil.dll adlı özel imzalama/doğrulama binary’si ise ağırlıklı olarak Windows ve x86 Linux için dağıtıldığından macOS veya Arm Linux CI üzerinde çevrimdışı DirectX shader derlemesi engellenir
mach-dxcompiler, CMake derlemesini Zig build.zig ile yeniden yazarak DLL bağımlılığını kaldırır ve statik dxcompiler kütüphanesi ile dxc CLI sağlar; ancak MSVC ABI, musl testleri, SPIR-V çıktısı ve SM6.7 desteği konusunda sınırlamalar devam eder
Mach neden DXC’yi yeniden derledi?
- Mach engine, Zig ile sysgpu adlı deneysel bir grafik API’si geliştiriyor ve Metal, Vulkan, Direct3D, OpenGL backend desteğini hedefliyor
- Direct3D 12 backend’inde shader programlarının Direct3D 12’nin tüketebileceği bir formata derlenmesi gerekiyor
- Bu süreçte Microsoft’un DirectX shader derleyicisi DXC’nin oyun geliştiricileri için karmaşık ve zahmetli bir dağıtım deneyimi yarattığı ortaya çıktı
FXC’den DXC’ye geçen DirectX shader derlemesi
- DirectX grafik API’si, shading dili olarak HLSL kullanır
- Direct3D 11’den önceki HLSL derleyicisi FXC, yani effects compiler olarak adlandırılıyordu
- FXC, oyun geliştiricileri arasında yavaş ve kod üretim kalitesi iyi olmayan bir derleyici olarak bilinir
- Hem shader derleme hızı hem de çalışma zamanı performansı açısından dezavantajlı olabilir
- Direct3D 12 ve Shader Model 6.0 ile Microsoft, Windows OS’ye dahil edilen FXC’yi resmen deprecated ilan etti ve LLVM/Clang v3.7 tabanlı fork’u olan DXC’yi tanıttı
- DXC, Microsoft/DirectXShaderCompiler olarak açık kaynak yayımlanıyor; Microsoft ayrıca önceden derlenmiş binary’ler de dağıtıyor
- Microsoft’un LLVM fork’unda HLSL ile ilgili değişiklikler
// HLSL Change Start, // HLSL Change End yorumlarıyla işaretlenmiş durumda
Direct3D sürücülerinin tükettiği DXBC ve DXIL
- Her GPU üreticisinin donanım mimarisi ve gereksinimleri farklı olduğundan, HLSL’in sonunda çalıştırıldığı yerel binary de Intel, NVIDIA ve AMD GPU’larda farklıdır
- Microsoft, Direct3D ve HLSL gibi frontend API’leri sağlar; Intel, AMD ve NVIDIA gibi IHV’ler ise bunları donanım ISA’sına yakın bir biçime bağlayan sürücüleri yazar
- DirectX 9~11’de sürücüler DXBC tüketir
- Oyun geliştiricileri HLSL’i
fxc.exe CLI veya d3dcompiler API ile DXBC’ye derler
- Sürücü, DXBC’yi gerçek GPU’da çalışacak binary’ye dönüştürür
- DXBC, Microsoft ile GPU sürücü üreticileri arasında kullanılan kapalı ve özel bir formattı
- DirectX 12 ve Shader Model 6.0’dan sonra DXIL, DirectX 12 sürücü üreticilerinin tükettiği resmi format oldu
- DXIL, LLVM 3.7’nin kod üretimi ve optimizasyon pass’lerinden sonraki bitcode formatına küçük bir özel container/wrapper eklenmiş hâline yakındır
- DXIL dokümantasyonu, ayrı bir spesifikasyondan ziyade Microsoft’un LLVM 3.7 fork’unun HLSL değişiklikleri ve optimizasyonlardan sonra fiilen ürettiği bitcode’a dayanır
Kaybolan DXIR planı ve LLVM upstream’e geçiş
- Microsoft, DirectX 12 ve Shader Model 6.0 döneminde yüksek seviyeli, optimize edilmemiş IR olan DXIR’i oluşturmayı ve DXC’nin bunu optimize edilmiş DXIL’e lowering yapmasını tasarlamıştı
- 2021’de DXIR oluşturma olasılığına işaret eden ifadeler kaldırıldı
- 2019’da bir Microsoft çalışanı, DXIR’den DXIL’e lowering sürecine ilişkin dokümantasyonun neredeyse olmadığını; DXIR’in resmi bir format değil, CodeGen sonrası ilk LLVM IR’ye yakın olduğunu söyledi
- 2023’te bir Microsoft çalışanı, DXC’nin LLVM fork’unun LLVM’in kod üretim katmanının ve altyapısının önemli bölümünü kaldırdığını veya bozduğunu açıkladı
- DXC’ye DXBC üretimi eklemek için bozuk LLVM işlevlerinin onarılması gerekir; DXC’de bunun ele alınmayacağını belirtti
- Microsoft, Mart 2022’den bu yana HLSL derleme desteğini ana LLVM/Clang hattına upstream etme çalışmasını önerdi ve sürdürüyor
- Bu geçiş planı, modern LLVM/Clang’e eski LLVM v3.7 bitcode writing desteğini yeniden ekleme işini de içeriyor
WebGPU ve oyun motorları için DXC dağıtım yükü
- Metal, Direct3D 12 ve Vulkan gibi modern grafik API’lerini birleştirmeyi amaçlayan grafik soyutlama katmanları için birleşik bir shading dili de gerekir
- Güncel WebGPU uygulamaları uzun vadede DXIL’i doğrudan üretme yolunu hedefleyebiliyor; ancak pratikte çoğu bunu yapmıyor
- Tipik WebGPU yolu şöyledir
- WGSL metin dili runtime’da HLSL’e dönüştürülür
- HLSL, bir HLSL derleyicisiyle DXBC veya DXIL’e derlenir
- Optimize edilmiş DXBC/DXIL grafik sürücüsüne verilir; sürücü de bunu üreticiye özgü ara temsile ve makine koduna dönüştürür
- Vulkan/SPIR-V’de de sürücünün SPIR-V’yi yerel binary’ye derlemesi gereken bir yapı vardır
- Bazı sürücüler SPIR-V’nin optimize edildiğini varsayabilir; ancak bu mobil ve masaüstü GPU’ya göre değişir
- Valve’ın Fossilize aracı, GPU ve sürücü sürümü kombinasyonlarına göre sürücünün derlediği gerçek binary cache’ini tutar
- DXIL her zaman optimizasyon pass’lerinden sonraki LLVM bitcode iken, SPIR-V optimize edilmiş biçimde de olabilir, olmayabilir de
- Yalnızca Apple Metal, gerçek hedef donanımın yerel binary formatına doğrudan derleme yapan bir API’yi destekler
dxcompiler.dll ve dxil.dll’in yarattığı seçenekler
- WebGPU runtime’ı WGSL→HLSL→DXIL dönüşümünü runtime’da gerçekleştirdiğinden, yeni DXC ile eski FXC arasında seçim yapmak zorundadır
- Bevy dokümantasyonuna göre FXC eski, yavaş ve bakımı yapılmıyor; ancak ek DLL dağıtımı gerektirmiyor
- Buna karşılık DXC yeni, hızlı ve bakımı yapılan bir araç; ancak uygulamayla birlikte
dxcompiler.dll ve dxil.dll dağıtmak gerekiyor
- Bu seçim problemi yalnızca Bevy’yi değil,
wgpu Rust kullanıcılarını ve Dawn WebGPU kullanıcılarını da etkiliyor
- Sonuç olarak birçok yazılım eski, yavaş ve bakımı yapılmayan FXC’yi varsayılan seçenek yapıyor
DXC’yi statik linklemenin zor olmasının nedeni
- Microsoft’un LLVM fork’u statik linklemeyi desteklemiyor
- CMake dosyalarında
SHARED STATIC ile değiştirildiğinde yaklaşık 15 statik kütüphane oluşuyor; ancak linkleme deneyimi tek bir kütüphaneye göre daha kötü oluyor
- CMake
OBJECT kütüphanesi kullanılmaya çalışıldığında, Microsoft’un HLSL değişiklikleri nedeniyle mantıksal bağımlılıklardan bağımsız örtük karşılıklı bağımlılıklar ortaya çıkıyor
- DXC’nin COM arayüzü uygulamalarının bir kısmı,
dxcompiler.dll ve dxil.dll dosyalarını dinamik kütüphane olarak yükleyip kendi kendini çağıracak şekilde tasarlanmış
- Yalnızca derleme ayarlarını değiştirmekle statik DXC oluşturmak zor
Özel dxil.dll ve shader imzalama
dxil.dll, DirectXShaderCompiler kaynak koddan derlense bile oluşturulmaz; ancak GitHub release’lerinde Windows x86/Arm ve Linux x86 için dağıtılır
- D3D12 Shader Cache API specification’a göre D3D12 yalnızca imzalı shader’ları kabul eder; runtime optimizasyonu veya patch uygulanırsa shader’ın yeniden doğrulanıp imzalanması gerekir
- Shader Model 6.8 preview release’inde
dxil.dll/libdxil.so sağlanmaz
- Bu derleyicinin ürettiği SM6.8 hedefli DXIL nihai sürüm değildir ve doğrulanamaz
- Developer Mode’da olmayan makinelerde dağıtım veya çalıştırma desteklenmez
dxil.dll yoksa shader imzalanmaz/doğrulanmaz
- İmzalanmamış/doğrulanmamış shader’lar, Windows makinesi Developer Mode’da değilse çalıştırılamaz
Çevrimdışı derleme ve platform kısıtları
- Mach, gerektiğinde ağır DXC bağımlılığı dağıtımından kaçınmak ve çevrimdışı shader derlemesi yapmak istiyor
- Microsoft,
dxil.dll’i yalnızca Windows x86/Arm ve Linux x86 için dağıtıyor
- Linux aarch64 binary’si ve macOS binary’si sağlanmıyor
- Bu yüzden macOS’ta Windows için çapraz platform oyun derlemesi oluşturmak veya Arm Linux CI pipeline’ında çevrimdışı DirectX shader derlemesi yapmak mümkün olmuyor
- Özel imzalama binary’sini çalıştırmak için Windows veya x86_64 Linux makinesi gerekiyor
mach-dxcompiler neleri değiştirdi?
- Mevcut CMake derleme sisteminin yaklaşık 10,5 bin satırı Zig’in
build.zig dosyasıyla yeniden yazıldı
- Tüketicilerin çoğunlukla ihtiyaç duyduğu iki bölüm, yani
dxcompiler.dll kütüphanesi ve dxc.exe çevrimdışı derleme/test binary’si derleme hedefi yapıldı
- Sonuçta yaklaşık 1 bin satırlık
build.zig mantığı ile sadeleştirildi
- DXC’nin
dxcompiler.dll ve dxil.dll varlığını bekleyen yapısını düzeltmek için Microsoft codebase’i fork’landı
- DLL entrypoint simüle edildi
- DLL’den gelen derleyici sürümü bilgisi çıktısı devre dışı bırakıldı
- Dinamik kütüphane fonksiyon pointer’larının yüklenmesi emüle edildi
mach-dxcompiler, dxil.dll’ye bağımlı olmayan bir biçimde yapılandırılmıştır
- macOS makinesinde özel
dxil.dll olmadan HLSL shader’ları derleyip, normal Windows makinelerinde çalışan DXIL bytecode ile byte-for-byte aynı dosyalar üretmek mümkündür
Çıktılar ve kullanım yöntemi
- Release, statik
dxcompiler kütüphanesi ve dxc CLI için önceden derlenmiş binary’ler içerir
- Özel
dxil.dll bağımlılığı yoktur
- CI pipeline’ında derlenen hedefler şunlardır
- macOS: Apple Silicon aarch64 ve Intel x86_64
- Linux: musl ve glibc, aarch64 ve x86_64
- Windows: x86_64 ve aarch64, MinGW/GNU ABI dahil
- Kütüphane, mevcut COM API’ye alternatif olarak küçük bir C API sunar
- Zig oyun geliştiricileri depodaki Zig API’yi kullanabilir; kullanım örnekleri
src/main.zig testlerinde görülebilir
- Varsayılan olarak önceden derlenmiş binary’ler indirilip kullanılır
- Kaynaktan derleme mach-dxcompiler deposunda yalnızca
zig ve git ile yapılabilir; belirtilen Zig sürümü gerekir
git clone https://github.com/hexops/mach-dxcompiler
cd mach-dxcompiler/
zig build -Dfrom_source -Dtarget=aarch64-macos
zig build -Dfrom_source -Dtarget=x86_64-windows-gnu
zig build -Dfrom_source -Dtarget=x86_64-linux-gnu
Mevcut sınırlamalar ve bakım koşulları
- Windows MSVC ABI binary’leri, C binding’deki küçük bir hata nedeniyle şu anda derlenmiyor
- Linux musl binary’leri derleniyor ancak henüz test edilmedi
- Mach engine, HLSL yerine Zig’in kendisini shading dili olarak kullanmayı planladığından SPIR-V çıktı desteği derlenmiyor ve bunun için ek plan yok
- Yakın zamanda yayımlanan SM6.7 destek güncellemesi için şu anda bir plan yok
- LLVM’in CMake derleme sisteminin bazı bölümleri henüz tamamen taşınmadı; ilgili ayrıntılar
generated-include/ içinde duruyor
- Bu proje Mach’in sorununu çözmek için var ve şu anda issue’ları tek bir kişinin ele aldığı bir yapıda
- Daha iyi bir yol bulunursa proje deprecated olabilir
1 yorum
Hacker News yorumları
Çapraz 3D API shader derleme altyapısının ne kadar dağınık olduğunu iyi özetleyen bir yazı.
D3D ve Microsoft’a odaklanıyor ama diğer 3D API’ler de pek daha iyi değil. Örneğin Linux host’larda Metal shader’larını çapraz derleyemiyorsunuz; bu yalnızca macOS’te ve nispeten yeni Windows sürümlerinde mümkün.
Mach ekibi Zig’i çapraz 3D API shader derleyicisi olarak kullanma fikrini “çapraz derleme araç zinciri olarak Zig” kadar sorunsuz hâle getirebilirse, bu bilgisayar grafikleri alanında yaklaşık 1995’ten beri yaşanan en büyük gelişme olabilir.
Bunun Godot ile de ilgisi var.
“Bunu isteğe bağlı hâle getirmemizin nedeni, Direct3D 12 desteğinin şu anda DirectX Shader Compiler’ın Godot ile birlikte dağıtılan özel mülk dxil.dll kitaplığına bağlı olması ve özel mülk yazılım dağıtmanın Godot projesinin misyonuna aykırı olması” deniyor.
https://godotengine.org/article/dev-snapshot-godot-4-3-dev-3...
GPU’mun, Wi‑Fi’ımın ve Bluetooth’umun çalışmasını istiyorum; varsayılan olarak işaretli olması iyi olurdu.
“Uygulamayla birlikte ek bir .dll dağıtmaya gerek yok” kısmına gelince, birçok video oyunu zaten Bink, SpeedTree, PhysX gibi özel mülk ara yazılımları bu şekilde dağıtıyor.
Steam, GOG, Epic gibi çoğu başlatıcı da kendi .DLL’lerini gerektiriyor ve birçok oyun D3D11On12 kullanıyor. Kurulu dosya listesinde dxil.dll bulunan çok sayıda yayımlanmış oyun da var.
Bu yüzden gerçekten merak ediyorum: bir DLL daha dağıtmanın sorunu ne? Burada kod imzalamayı tersine mühendislikle çözmek ve yeniden uygulamak harika bir iş; özellikle de çıktısının dxil.dll ile bit düzeyinde aynı olması etkileyici. Ama ben aşırı tembel olduğum için muhtemelen daha kolay yolu, yani DLL dağıtmayı seçerdim.
Örneğin Mach motoru, Zig kodunu hedef platformlar genelinde shader’lara derleyen bir derleyici oluştururken bunu kullanabilir; son kullanıcı da ek yapılandırma veya bağımlılık olmadan Mach’in temel işlevleri içinde doğrudan kullanabilir.
AAA oyunlarda bile, diğer oyun ve yazılımlarda da kontrolünüz dışında bozulabilecek ek bağımlılıklar artar. Eskiden çalıştığım şirkette, bir ara yazılımı yalnızca DLL ve kütüphane biçiminde alıp linklemek zorunda olduğumuz için Visual Studio yükseltmelerine daha fazla emek harcadık ve yeni sürümü de almamız gerekti. Ara yazılım şirketi kendi tarafındaki yükseltmeyi yapmadığı için yeni VS uyumluluk QA’sını da biz yapmak zorunda kaldık.
Elbette kaynak kodun olması güncellemenin sürtünmesiz olacağı anlamına gelmez, ama sürtünme çok azalır ve başkasını beklemek zorunda kalmazsınız. Son dönemde Visual Studio’nun ikili C++ kütüphanelerinde geriye dönük uyumluluk sağlamaya çalıştığı görülüyor, ancak bunun uzun vadede güvenilebilecek bir özellik olduğunu düşünmüyorum.
Ayrıca tüm bunlar, kodun aynı platform ve hedefte kaldığı varsayımı altında geçerli. Bir noktada başka platformları host ya da hedef olarak ele almak isteyebilirsiniz; kaynak kod yoksa bu son derece zor ya da imkânsız hâle gelebilir. DXIL gibi platforma özgü bir şey için bu büyük bir sorun gibi görünmeyebilir, ancak yazıda da DXIL’in ikili blob niteliği nedeniyle Microsoft’un DLL sağladığı belirli Windows ve Linux mimarileri dışında shader’ları önceden derlemenin mümkün olmadığı söyleniyor.
DXIL.dll’nin yaptığı “imza”[1] nihayetinde değiştirilmiş bir MD5’ten ibaret mi?
1: https://github.com/hexops/DirectXShaderCompiler/blob/4190bb0...
Yazıyı o noktaya kadar dikkatle okuyan biri bunun temel bir hash ya da benzeri bir şey olması gerektiğini anlayabilirdi; en kötü ihtimalle de birinin assembly’yi tersine mühendislikle çözmesi yeterliydi
Bu kadar uğraştıktan sonra Microsoft’u açıkça eleştirmek gayet olur. Hele de ilgilenen herkesin kazıp bulabileceği açık kaynak koddan söz ediliyorsa; ayrıca bunu bulduğu için msk’ye teşekkürler
https://github.com/baldurk/renderdoc/blob/4a620bb5a16b4de4e2...
Microsoft tarafındaki şu alıntı[0] hoşuma gitti. DXC’nin LLVM fork’u, LLVM’in kod üretim katmanını ve altyapısının büyük kısmını kaldırdığı ya da bozduğu için, DXC’de DXBC üretimini desteklemek kırık LLVM özelliklerini düzeltip geri getirmeye yönelik büyük bir çalışma gerektirirmiş
Sorunun kapsamı büyük ve ekip kaynakları sınırlı olduğundan yeni DXC derleyicisinde bu sorunu çözmeyeceklerini; ileride Clang’de DXBC üretimi desteklenebilse de şimdilik DXIL ve SPIR-V üretim desteğine odaklandıkları için buna birkaç yıl başlanmasının zor olduğunu söylüyorlar. Yapılmayacak işleri net biçimde söylemeleri ferahlatıcı
[0] https://github.com/microsoft/DirectXShaderCompiler/issues/57...
Mach ekosistemine mutlaka bakmanızı öneririm. Özellikle mach-sysgpu, WebGPU’nun eksiksiz bir yeniden uygulanışı ve büyük kısmını 17 yaşındaki Ali Chraghi yazmış
SDL tarafında, SDL3’e eklemek üzere mevcut olandan farklı SDL_gpu biçiminde bir shader dili geliştiriliyor. Oyunlara yönelik 3D grafiklerle çalışırken çapraz platform bir yol olabileceği için bir süredir dikkatle takip ediyorum
Fark olarak SDL_gpu hâlâ erken aşamada, WebGPU’nun ise şimdiden iyi iki açık uygulaması var denebilir
Daha az baş ağrıtan yöntem muhtemelen HLSL/GLSL → SPIR-V ↔ DXIL gibi bir şey ya da shader’ları doğrudan SPIR-V olarak yazmak olurdu
Wine’ın vkd3d’sinde DXIL → SPIR-V dönüştürücüsü var gibi görünüyor; yüksek seviyeli shading dili dönüştürücülerine göre çok daha basit bir ara dil olduğundan daha sağlam olabilir
Yine de şu LLVM canavarı dışında, GCC ya da Clang olmadan derlenebilen saf ve basit C99 tabanlı bir HLSL → DXIL derleyicisi olup olmadığını merak ediyorum
Soruyu yanıtlamak gerekirse: yok. HLSL’den DXIL’e dönüşüm fiilen Microsoft’un elinde ve bundan uzaklaşmaya yönelik pek çaba olmadı
Zig’in kendisini shading dili olarak kullanmak harika. Zig gerçekten tek dil. Aynı zamanda bir build sistemi, aynı zamanda bir shading dili!