Shader交叉編譯之夢
我有個夢想,有一天,在各個平臺上,HLSL將能夠和GLSL、Metal SL坐在一起,共敘兄弟情誼。
我有個夢想,就在今天。
去年年初,我寫過一篇文章: ofollow,noindex" target="_blank">跨平臺shader編譯的過去、現在和未來 。介紹了一下從2003年以來為了解決跨平臺跨語言的shader編譯的各種方法和所經歷的種種痛苦。緊接著我又 開了個新專案,Dilithium ,試圖從DXIL轉換到SPIR-V,從二進位制層面解決轉換的問題。然而進展頗為不順。一方面是在探索中發現等到生成DXIL的時候,已經損失了太多資訊,不足以很好地轉換出SPIR-V。另一方面是google的團隊加入DirectXShaderCompiler的開發,實現了我在文章裡說的重要一環:HLSL->SPIR-V編譯器,也就是SPIR-V的程式碼生成後端。隨著這個後端逐步成熟,似乎,第一次,我們有機會開發一個完全沒有逆向工程,不需要猜測,每個環節都有官方支援Shader交叉編譯系統。十五年來,無數次失敗,無數回推倒重來,無數行不靠譜的湊活程式碼,現在終於有一勞永逸的可能了。
兩週前,經過一個20分鐘的超短探索,我發現,我的這個想法是可行的。接下來我便專注於把這個想法實現成程式碼。幾個小時後,一個原型系統逐步成形。HLSL可以編譯成多種不同的Shader語言,每種語言還可以帶上不同的版本。又經過一些努力,這個專案現在已經正式開源。我把它命名為 ShaderConductor ,希望能像超導體那樣,用很小的開銷,把Shader從一個語言導到另一個語言。專案已經公開在github上,通過微軟組織開源: Microsoft/ShaderConductor 。
這個系統的輸入和輸出相當符合我當初的夢想。
- 輸入是 HLSL ,不管哪個平臺,都用同一個版本的HLSL。
- HLSL經過 DirectXShaderCompiler 的編譯,可以生成D3D12用的 DXIL ,也可以生成Vulkan和較新的OpenGL用的 SPIR-V 。在不同的平臺上,跑的是完全相同的前端解析程式碼。
- SPIR-V經過 SPIRV-Cross ,可以轉換成OpenGL用的 GLSL ,OpenGL ES用的 ESSL ,Metal用的 MSL ,以及D3D 9/10/11用的 老HLSL 。完成了對各個主流平臺的覆蓋。

這兩個元件,一個來自於微軟官方,可以保證HLSL編譯部分不存在相容問題;另一個來自於Khronos官方,可以保證SPIR-V轉換回高階語言部分不存在相容問題。並且兩者都支援Windows,macOS,Linux等多個平臺。ShaderConductor把它們連在一起後,拼圖完整了!一個HLSL到各個語言的跨平臺交叉編譯系統就此誕生。
除了技術問題,在這兩週準備開源的過程中還經歷了一些非技術的挫折。(寫出來又是一部血淚史,有血,有淚,有shi)然而無論如何,現在都已經克服了,專案成功地經過審查,公開開源。當然,這個專案還在極早期的階段,還需要再使用中逐步完善。盡情期待。
We can be heroes, just for one day.