3 पॉइंट द्वारा GN⁺ 2024-02-11 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • Mach engine की experimental graphics API sysgpu को Direct3D 12 के लिए shader outputs की जरूरत थी, इसलिए Microsoft DXC को static और cross-platform तरीके से उपयोग में आसान रूप में फिर से build किया गया
  • Direct3D 12 का DXIL, Microsoft के LLVM/Clang 3.7 fork द्वारा output किए जाने वाले post-processed LLVM bitcode के करीब है, इसलिए इसकी संरचना specification से ज्यादा “actual compiler output” पर निर्भर करती है
  • WebGPU family runtimes आम तौर पर WGSL को HLSL में बदलने के बाद FXC या DXC से DXBC/DXIL बनाते हैं, लेकिन DXC को distribute करने की परेशानी की वजह से पुराना और धीमा FXC default बन जाना आसान है
  • मौजूदा DXC को static link करना कठिन है, और dxil.dll नाम का proprietary signing/verification binary मुख्य रूप से Windows और x86 Linux के लिए ही distributed है, जिससे macOS या Arm Linux CI पर offline DirectX shader compilation रुक जाता है
  • mach-dxcompiler CMake build को Zig build.zig में फिर से लिखता है और DLL dependency हटाकर static dxcompiler library और dxc CLI देता है, लेकिन MSVC ABI, musl tests, SPIR-V output और SM6.7 support में अभी सीमाएं बची हैं

Mach ने DXC को फिर से build क्यों किया

  • Mach engine Zig में sysgpu नाम की एक experimental graphics API बना रहा है, जिसका लक्ष्य Metal, Vulkan, Direct3D और OpenGL backend support है
  • Direct3D 12 backend में shader programs को ऐसे format में compile करना पड़ता है जिसे Direct3D 12 consume कर सके
  • इस प्रक्रिया में यह सामने आया कि Microsoft का DirectX shader compiler DXC game developers के लिए जटिल और असुविधाजनक distribution experience बनाता है

FXC से DXC तक DirectX shader compilation का बदलाव

  • DirectX graphics API shading language के रूप में HLSL का उपयोग करती है
  • Direct3D 11 से पहले का HLSL compiler FXC, यानी effects compiler, कहलाता था
  • FXC game developers के बीच धीमे और खराब code generation quality वाले compiler के रूप में जाना जाता है
    • shader compilation speed और execution performance दोनों में यह disadvantage दे सकता है
  • Direct3D 12 और Shader Model 6.0 में Microsoft ने Windows OS में शामिल FXC को officially deprecated किया और LLVM/Clang v3.7 आधारित fork DXC पेश किया
  • DXC Microsoft/DirectXShaderCompiler के रूप में public है, और Microsoft pre-built binaries भी distribute करता है
  • Microsoft के LLVM fork में HLSL-related changes को // HLSL Change Start, // HLSL Change End comments से mark किया गया है

Direct3D drivers द्वारा consume किए जाने वाले DXBC और DXIL

  • हर GPU vendor की hardware architecture और requirements अलग होती हैं, इसलिए HLSL का final native binary भी Intel, NVIDIA और AMD GPUs के लिए अलग-अलग होता है
  • Microsoft Direct3D और HLSL जैसे frontend APIs देता है, और Intel·AMD·NVIDIA जैसे IHV drivers लिखते हैं ताकि इन्हें hardware ISA के करीब रूप से जोड़ा जा सके
  • DirectX 9~11 में drivers DXBC consume करते हैं
    • game developers fxc.exe CLI या d3dcompiler API से HLSL को DXBC में compile करते हैं
    • driver DXBC को actual GPU पर चलने वाले binary में बदलता है
    • DXBC Microsoft और GPU driver vendors के बीच इस्तेमाल होने वाला private proprietary format था
  • DirectX 12 और Shader Model 6.0 के बाद DXIL DirectX 12 driver vendors द्वारा consume किया जाने वाला official format बन गया
  • DXIL, LLVM 3.7 के code generation और optimization passes के बाद bitcode format में एक छोटा custom container/wrapper जोड़ने वाले रूप के करीब है
  • DXIL documentation किसी अलग specification से ज्यादा Microsoft के LLVM 3.7 fork द्वारा HLSL changes और optimization के बाद वास्तव में output किए जाने वाले bitcode पर निर्भर करती है

गायब हुआ DXIR plan और LLVM upstream में बदलाव

  • DirectX 12 और Shader Model 6.0 के समय Microsoft ने high-level, unoptimized IR DXIR बनाने और DXC द्वारा इसे optimized DXIL में lower करने की योजना बनाई थी
  • 2021 में DXIR बनाने की संभावना का संकेत देने वाली wording हटा दी गई
  • 2019 में Microsoft के एक कर्मचारी ने जवाब दिया कि DXIR से DXIL में lower करने की प्रक्रिया का documentation लगभग नहीं है, और DXIR कोई official format नहीं बल्कि CodeGen के बाद पहला LLVM IR जैसा है
  • 2023 में Microsoft के एक कर्मचारी ने बताया कि DXC के LLVM fork ने LLVM के code generation layer और infrastructure के बड़े हिस्से को हटा दिया या नुकसान पहुंचाया
    • DXC में DXBC generation जोड़ने के लिए टूटे हुए LLVM features को restore करना पड़ेगा, और DXC में वे इसे handle नहीं करेंगे
  • Microsoft ने मार्च 2022 से HLSL compilation support को LLVM/Clang mainline में upstream करने का काम propose किया और आगे बढ़ा रहा है
  • इस transition plan में modern LLVM/Clang में legacy LLVM v3.7 bitcode writing support को फिर से जोड़ने का काम भी शामिल है

WebGPU और game engines पर DXC distribution का बोझ

  • Metal, Direct3D 12, Vulkan जैसी modern graphics APIs को unify करने वाली graphics abstraction layers को unified shading language की भी जरूरत होती है
  • मौजूदा WebGPU implementations कभी-कभी long term में DXIL को direct emit करने वाला path target करती हैं, लेकिन practice में अधिकांश ऐसा नहीं करतीं
  • आम WebGPU path इस तरह है
    • WGSL text language को runtime पर HLSL में convert किया जाता है
    • HLSL को HLSL compiler से DXBC या DXIL में compile किया जाता है
    • optimized DXBC/DXIL को graphics driver को दिया जाता है, और driver इसे vendor-specific intermediate representation और machine code में बदलता है
  • Vulkan/SPIR-V भी ऐसा structure है जहां driver को SPIR-V को native binary में compile करना होता है
    • कुछ drivers मान सकते हैं कि SPIR-V optimized है, लेकिन यह mobile और desktop GPU के हिसाब से अलग होता है
    • Valve का Fossilize GPU और driver version combinations के हिसाब से driver द्वारा compile किए गए actual binary cache को maintain करता है
  • DXIL हमेशा optimization passes के बाद का LLVM bitcode होता है, जबकि SPIR-V optimized form में हो भी सकता है और नहीं भी
  • केवल Apple Metal ऐसा API support करता है जो actual target hardware के native binary format में direct compile करता है

dxcompiler.dll और dxil.dll से बनने वाले विकल्प

  • WebGPU runtime WGSL→HLSL→DXIL conversion runtime पर करता है, इसलिए उसे नए DXC और पुराने FXC में से एक चुनना पड़ता है
  • Bevy documentation के अनुसार FXC पुराना, धीमा और unmaintained है, लेकिन extra DLL distribution की जरूरत नहीं होती
  • इसके उलट DXC नया, तेज और maintained है, लेकिन application के साथ dxcompiler.dll और dxil.dll distribute करने पड़ते हैं
  • यह choice problem सिर्फ Bevy ही नहीं, बल्कि wgpu Rust users और Dawn WebGPU users को भी प्रभावित करती है
  • नतीजतन बहुत-सा software पुराने, धीमे और unmaintained FXC को default बना लेता है

DXC static linking कठिन क्यों है

  • Microsoft का LLVM fork static linking support नहीं करता
  • CMake files में SHARED को STATIC में बदलने पर करीब 15 static libraries बनती हैं, लेकिन single library की तुलना में linking experience खराब होता है
  • CMake OBJECT library का उपयोग करने की कोशिश करने पर Microsoft के HLSL changes की वजह से logical dependencies से अलग implicit mutual dependencies सामने आती हैं
  • DXC के COM interface implementation के कुछ हिस्से dxcompiler.dll और dxil.dll को dynamic libraries के रूप में load करके खुद को call करने के लिए designed हैं
  • सिर्फ build settings बदलने से static DXC बनाना मुश्किल है

proprietary dxil.dll और shader signing

  • dxil.dll DirectXShaderCompiler को source से build करने पर नहीं बनता, लेकिन GitHub releases में Windows x86/Arm और Linux x86 के लिए distribute होता है
  • D3D12 Shader Cache API specification के अनुसार D3D12 केवल signed shaders को स्वीकार करता है, और runtime optimization या patching होने पर shader को फिर verify और sign करना पड़ता है
  • Shader Model 6.8 preview release में dxil.dll/libdxil.so उपलब्ध नहीं है
    • उस compiler द्वारा generated SM6.8 target DXIL final नहीं है और verify नहीं किया जा सकता
    • Developer Mode में न होने वाली machines पर distribution या execution support नहीं है
  • dxil.dll न हो तो shaders sign/verify नहीं होते
  • sign/verify न किए गए shaders Windows machine के Developer Mode में न होने पर run नहीं हो सकते

offline compilation और platform constraints

  • Mach जरूरत पड़ने पर भारी DXC dependency distribution से बचना और offline shader compilation करना चाहता है
  • Microsoft dxil.dll को केवल Windows x86/Arm और Linux x86 के लिए distribute करता है
  • Linux aarch64 binaries और macOS binaries उपलब्ध नहीं हैं
  • इसलिए macOS पर Windows के लिए cross-platform game build बनाना या Arm Linux CI pipeline में offline DirectX shader compilation करना संभव नहीं है
  • proprietary signing binary चलाने के लिए Windows या x86_64 Linux machine की जरूरत होती है

mach-dxcompiler ने क्या बदला

  • मौजूदा CMake build system की लगभग 10.5k lines को Zig के build.zig में फिर से लिखा गया
  • consumers को मुख्य रूप से जिन दो हिस्सों की जरूरत होती है—dxcompiler.dll library और dxc.exe offline compilation/test binary—सिर्फ उन्हें build target बनाया गया
  • नतीजतन यह करीब 1k lines के build.zig logic में व्यवस्थित हो गया
  • DXC की dxcompiler.dll और dxil.dll की मौजूदगी की उम्मीद करने वाली structure को बदलने के लिए Microsoft codebase को fork किया गया
    • DLL entrypoint को simulate किया गया
    • DLL से आने वाली compiler version information output feature को disable किया गया
    • dynamic library function pointer loading को emulate किया गया
  • mach-dxcompiler को dxil.dll पर निर्भर न रहने वाले रूप में configure किया गया है
  • macOS machine पर proprietary dxil.dll के बिना HLSL shaders compile करके ऐसे DXIL bytecode files बनाए जा सकते हैं जो सामान्य Windows machines पर चलने वाले files से byte-for-byte identical हैं

output और उपयोग का तरीका

  • release में static dxcompiler library और dxc CLI के pre-built binaries शामिल हैं
  • proprietary dxil.dll dependency नहीं है
  • CI pipeline में build होने वाले targets ये हैं
    • macOS: Apple Silicon aarch64 और Intel x86_64
    • Linux: musl और glibc, aarch64 और x86_64
    • Windows: x86_64 और aarch64, MinGW/GNU ABI सहित
  • library मौजूदा COM API के alternative के रूप में छोटी C API expose करती है
  • Zig game developers repository की Zig API इस्तेमाल कर सकते हैं, और src/main.zig tests में usage examples देख सकते हैं
  • default रूप से pre-built binaries download करके इस्तेमाल किए जाते हैं
  • source build mach-dxcompiler repository में सिर्फ zig और git से किया जा सकता है, और specified Zig version की जरूरत होती है
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

मौजूदा सीमाएं और maintenance conditions

  • Windows MSVC ABI binaries C binding के एक छोटे bug की वजह से फिलहाल build नहीं होते
  • Linux musl binaries build होते हैं, लेकिन अभी test नहीं किए गए हैं
  • Mach engine HLSL नहीं बल्कि Zig को ही shading language के रूप में इस्तेमाल करने की योजना रखता है, इसलिए SPIR-V output support build नहीं करता और इसके लिए कोई आगे की योजना भी नहीं है
  • हाल में release हुए SM6.7 support update की अभी कोई योजना नहीं है
  • LLVM के CMake build system के कुछ हिस्से अभी पूरी तरह migrate नहीं हुए हैं, और related details generated-include/ में बची हैं
  • यह project Mach की problem solve करने के लिए मौजूद है, और फिलहाल एक व्यक्ति issues handle कर रहा है
  • अगर बेहतर path मिलता है तो project deprecated हो सकता है

1 टिप्पणियां

 
GN⁺ 2024-02-11
Hacker News की राय
  • cross-3D API shader compile की बुनियादी स्थिति कितनी बिखरी हुई है, इस पर यह एक बहुत अच्छी तरह से व्यवस्थित लेख है
    यह D3D और Microsoft पर फोकस करता है, लेकिन दूसरे 3D API भी कोई खास बेहतर नहीं हैं। उदाहरण के लिए, Linux host पर Metal shader को cross-compile नहीं किया जा सकता, और यह केवल macOS तथा अपेक्षाकृत नए Windows पर ही संभव है
    अगर Mach टीम Zig को cross-3D API shader compiler के रूप में इस्तेमाल करने की योजना को “cross-compile toolchain के रूप में Zig” जितना सहज बना सके, तो यह 1995 के बाद से computer graphics में सबसे बड़ी घटनाओं में से एक हो सकती है

    • अगर ऐसा होता है, तो Zig के लिए भी यह बहुत बड़ी अच्छी खबर होगी। language के रूप में भी, और toolchain के रूप में भी इसकी ताकत बढ़ेगी
    • यह क्यों है कि Linux host पर Metal shader को cross-compile नहीं किया जा सकता, इसे लेकर जिज्ञासा है। क्या इसका मतलब सिर्फ इतना नहीं कि अभी तक किसी ने इसे implement नहीं किया है?
    • अगर यह Windows पर संभव है, तो क्या इसका मतलब नहीं कि Wine के ज़रिए Linux पर भी संभव होना चाहिए?
  • इसका Godot से भी संबंध है
    कहा गया है, “इसे optional बनाने का कारण यह है कि Direct3D 12 support फिलहाल DirectX Shader Compiler की proprietary dxil.dll library को Godot के साथ distribute करने पर निर्भर करता है, और proprietary software का distribution Godot project के mission के खिलाफ जाता है”
    https://godotengine.org/article/dev-snapshot-godot-4-3-dev-3...

    • यह जानने की जिज्ञासा है कि dxil/dxc का ठीक कौन-सा हिस्सा proprietary है। https://github.com/microsoft/DirectXShaderCompiler के license वाले उलझे हुए हिस्से को समझने की कोशिश कर रहा हूँ
    • end user को शायद इन बातों की बिल्कुल परवाह नहीं होगी। यह कुछ वैसा ही है जैसे कुछ Linux distributions install करते समय पूछती हैं, “क्या आप third-party drivers download और install करना चाहते हैं?”
      मैं चाहता हूँ कि मेरा GPU, Wi‑Fi, Bluetooth काम करे, इसलिए अच्छा होगा अगर यह default रूप से checked हो
    • क्या dxil.dll managed code, यानी “dotnet” code नहीं है?
  • “application के साथ अतिरिक्त .dll distribute करने की ज़रूरत नहीं है” वाले हिस्से पर, बहुत से video games पहले से ही Bink, SpeedTree, PhysX जैसे proprietary middleware को इसी तरह distribute करते हैं
    Steam, GOG, Epic जैसे ज़्यादातर launchers भी अपनी-अपनी .DLL की मांग करते हैं, और बहुत से games D3D11On12 का उपयोग करते हैं। ऐसे कई released games हैं जिनकी installed files की सूची में dxil.dll शामिल है
    इसलिए सच कहूँ तो जिज्ञासा है, एक और DLL distribute करने में समस्या क्या है? यहाँ code signing को reverse engineer करके फिर से implement किया गया काम शानदार है, और खासकर यह कि इसका output dxil.dll के साथ bit-level पर एक जैसा है, यह प्रभावशाली है। लेकिन मैं इतना आलसी हूँ कि शायद आसान रास्ता, यानी DLL distribute करना, ही चुनता

    • यह open source implementation मौजूदा game engines में इस तरह शामिल की जा सकती है कि programmer को यह जानने या समझने की ज़रूरत भी न पड़े कि dxil.dll क्या है
      उदाहरण के लिए, Mach engine इसे तब इस्तेमाल कर सकता है जब वह Zig code को target platform के लिए shaders में compile करने वाला compiler बना रहा हो, और end user इसे किसी अतिरिक्त setup या dependency के बिना Mach की core functionality के हिस्से के रूप में सीधे इस्तेमाल कर सकता है
    • games में सिर्फ AAA games ही नहीं होते, और graphics applications भी सिर्फ games नहीं होते। औसत 100GB AAA game के लिए जो बात ठीक है, वह itch.io के 30MB game पर, जिसमें 24MB सिर्फ DXC हो, या किसी व्यक्तिगत website के 3D model viewer·converter·animator पर लागू नहीं हो सकती
      AAA games में भी, और दूसरे games व software में भी, अतिरिक्त dependency बढ़ जाती है जो आपके नियंत्रण से बाहर टूट सकती है। जिस कंपनी में मैं पहले काम करता था, वहाँ हमें कुछ middleware सिर्फ DLL और library के रूप में मिलती थी और उसी से link करना पड़ता था, इसलिए Visual Studio upgrade पर ज़्यादा मेहनत लगती थी, और नया version भी लेना पड़ता था। उस middleware कंपनी ने अपनी तरफ से upgrade तैयार नहीं किया था, इसलिए हमें नए VS compatibility QA तक करनी पड़ी
      बेशक source code होने से updates पूरी तरह frictionless नहीं हो जाते, लेकिन friction काफी कम हो जाती है और किसी दूसरे का इंतज़ार भी नहीं करना पड़ता। हाल के Visual Studio ने binary C++ libraries के लिए backward compatibility की कोशिश की है, लेकिन मुझे नहीं लगता कि यह ऐसी चीज़ है जिस पर लंबी अवधि के लिए निर्भर रहा जा सकता है
      और यह सब इस मान्यता के तहत है कि code उसी platform और target पर बना रहेगा। किसी बिंदु पर आप किसी दूसरे platform को host या target के रूप में संभालना चाह सकते हैं, और source code न होने पर यह बेहद कठिन या असंभव हो सकता है। DXIL जैसी platform-specific चीज़ के लिए यह बहुत बड़ी समस्या न लगे, लेकिन लेख में भी कहा गया है कि DXIL के binary blob होने की वजह से, Microsoft ने जिन खास Windows और Linux architectures के लिए DLL दिया है, उनके बाहर shader precompilation संभव नहीं था
    • जैसा आपने कहा, अपने-आप में यह कोई बहुत बड़ी समस्या नहीं है। लेकिन लेख के अंत का सचमुच दिलचस्प बिंदु यह है कि किसी भी OS/architecture पर cross-build किया जा सकता है
  • क्या DXIL.dll जो “signature”[1] करता है, वह आखिरकार सिर्फ़ एक बदला हुआ MD5 ही है?
    1: https://github.com/hexops/DirectXShaderCompiler/blob/4190bb0...

    • Mach की पोस्ट शानदार है, फिर भी यह साफ़-साफ़ न बताना कि वह “signature” क्या है, थोड़ा खटकता है
      जिसने उस लेख को वहाँ तक ध्यान से पढ़ा होगा, वह समझ सकता था कि यह कोई बेसिक hash या वैसी ही चीज़ होगी, और सबसे बुरी स्थिति में भी कोई assembly को reverse engineer करके पता लगा सकता था
      इतना सब करने के बाद Microsoft की खुलकर आलोचना करना भी ठीक है। खासकर जब बात open source code की हो, जिसे रुचि रखने वाला कोई भी व्यक्ति खंगालकर ढूँढ सकता है; और इसे ढूँढ निकालने वाले msk का धन्यवाद
    • HN की यही बात सच में अच्छी लगती है। यहाँ ऐसे लोग हैं जो किसी random C code को memory के साथ काम करते देखकर कह सकते हैं, “यह modified X जैसा लग रहा है।” मेरे जैसे, जो ज़्यादातर high-level language इस्तेमाल करते हैं, लोगों के लिए यह काफ़ी हैरान करने वाली बात है
    • RenderDoc के पास 2021 से इसे संभालने वाला code था, और इसमें अच्छी तरह समझाने वाले comments भी हैं
      https://github.com/baldurk/renderdoc/blob/4a620bb5a16b4de4e2...
    • वह “signature” हमेशा से बकवास जैसा security theater ही था। यह इस बात से साफ़ है कि बाकी सभी graphics API उसके बिना भी ठीक से चलती हैं। अच्छा लगा कि किसी ने “signature” algorithm को सार्वजनिक रूप से पोस्ट किया
  • Microsoft की तरफ़ से यह quote[0] पसंद आया। इसमें कहा गया है कि DXC का LLVM fork, LLVM की code generation layer और infrastructure का बड़ा हिस्सा हटा चुका है या बिगाड़ चुका है, इसलिए DXC में DXBC generation support करने के लिए LLVM की टूटी हुई functionality को ठीक और restore करने का बड़ा काम करना पड़ेगा
    समस्या का दायरा बड़ा है और टीम के resources सीमित हैं, इसलिए नया DXC compiler इस समस्या को हल नहीं करेगा; भविष्य में Clang में DXBC generation support आ सकता है, लेकिन अभी DXIL और SPIR-V generation support पर फोकस होने की वजह से इस पर काम शुरू होने में कई साल लग सकते हैं। क्या नहीं किया जाएगा यह साफ़-साफ़ बता देना ताज़गीभरा है
    [0] https://github.com/microsoft/DirectXShaderCompiler/issues/57...

  • Mach ecosystem को ज़रूर देखें। खासकर mach-sysgpu, जो WebGPU का पूरा reimplementation है, और इसका ज़्यादातर हिस्सा 17 साल के Ali Chraghi ने लिखा है

  • SDL की तरफ़ SDL3 में शामिल करने के लिए मौजूदा चीज़ों से अलग SDL_gpu शैली की shader language बनाई जा रही है। गेम के लिए 3D graphics संभालते समय यह cross-platform तरीका बन सकता है, इसलिए मैं इसे कुछ समय से ध्यान से देख रहा हूँ

    • यह जानने की उत्सुकता है कि SDL_gpu, WebGPU से अर्थपूर्ण रूप से अलग है या नहीं। इसके goals देखें तो यह DX12/Vulkan/Metal के ऊपर आसान access वाली minimum-common-denominator abstraction बनाने जैसा ही लगता है
      फ़र्क बस इतना दिखता है कि SDL_gpu अभी शुरुआती काम के चरण में है, जबकि WebGPU की पहले से दो अच्छी public implementations मौजूद हैं
  • कम सिरदर्द वाला तरीका शायद HLSL/GLSL → SPIR-V ↔ DXIL जैसा कुछ होगा, या फिर shaders सीधे SPIR-V में लिखना
    लगता है Wine के vkd3d में DXIL → SPIR-V converter है, और high-level shading language converter की तुलना में यह कहीं ज़्यादा simple intermediate language है, इसलिए शायद ज़्यादा robust हो
    लेकिन इस LLVM monster के अलावा, क्या कोई pure और simple C99-आधारित HLSL → DXIL compiler है जिसे GCC या Clang के बिना compile किया जा सके?

    • SPIR-V → DXIL निश्चित रूप से आकर्षक है और इसे explore करना चाहिए। अभी हाल में पता चला कि Mesa में spirv2dxil नाम का एक tool है, लेकिन HLSL → DXC → DXIL की तुलना में वह कितना robust है और उसमें features पर्याप्त हैं या नहीं, यह नहीं पता
    • “shaders सीधे SPIR-V में लिखना” बस ऐसा न करना पड़े
      आपके सवाल का जवाब दें तो, नहीं। HLSL से DXIL में conversion पर लगभग Microsoft का ही नियंत्रण है, और उससे बाहर निकलने की कोशिशें बहुत कम रही हैं
  • Zig को ही shading language की तरह इस्तेमाल करना शानदार है। Zig सच में एक single language है। यह build system भी है, और shading language भी!