龔神給微軟 Linux 子系統寫的支持 DirectX 9、11的代碼到底屬不屬於「驅動」?

為什麼我得到不同的答案?

補充不擼兔子的意見:

「你這問題漏洞太大。Linux下哪個程序需要DirectX了?parrallels的虛擬顯卡最多只是把OpenGL調用轉發到宿主機上。Linux子系統和Windows子系統在內核看來是同等地位的。應該不需要搞這套東西才對。

不提供CUDA真正的原因肯定不是不想做。而是已經做好了,發現Linux子系統下CUDA跑分比Windows子系統下快,這就尷尬了。因為要保密,他又不能對外這麼說,只能說不想做打發你了」

而且他竟然斷定龔神寫的根本就不是驅動:

他寫的那個應該是虛擬顯卡而不是什麼驅動吧。只是把Library OS裡面的調用轉發到外面。draw bridge和Linux子系統是兩個不同的項目啊。

對比龔神自己的回答:

完全矛盾啊。誰說的是對的呢?


唉。死不悔改,而且一錯再錯。

首先,問題是錯的。我在另一個帖子里Windows 10 給 Linux 子系統寫顯卡驅動的是一個人嗎,是誰呢?提到的是Direct3D9/11的驅動,是給Drawbridge寫的,而不是Linux子系統。他們在發展上有個先後的關係,但不是一個東西。題主對此完全一知半解的情況下,不仔細看就斷章取義,實在太胡攪蠻纏。

其次,不擼兔子的說法,基本每個點都是錯誤的。

「parrallels的虛擬顯卡最多只是把OpenGL調用轉發到宿主機上。「

不,那麼做行不通。(甚至parallels都拼錯了)

」Linux子系統和Windows子系統在內核看來是同等地位的。應該不需要搞這套東西才對。」

不,Linux子系統在Picoprocess里。Linux子系統和Windows本身是guest和host的關係。

「不提供CUDA真正的原因肯定不是不想做。而是已經做好了」

不,根本沒寫。而且如果你懂CUDA的話,就知道轉API容易,難點是顯存訪問和管理。

「只是把Library OS裡面的調用轉發到外面。「

不,那麼做行不通。

好了,現在我就來說說為什麼直接把API調用轉到外面行不通。會有很多細節,像題主和不擼兔子這樣沒做過的人根本不會了解。

1. 流量。

API調用看似簡單,只要把所有的API都轉出去,就行了。原先遠程桌面就是這麼做的。但缺點是,API調用所要消耗的流量遠大於在驅動層搞。舉個例子,把同一個設置狀態調用兩次,你就得在API層轉兩次。最多就是cache一下,把變化的傳了。而在D3D的體系里,有runtime做狀態管理,只會把真正修改了有起作用的狀態往下傳給驅動,並會做嚴格的狀態驗證。所以在驅動層,你所需要轉的數據遠少於API層。

2. 出錯控制。

如果運行過程出了嚴重問題,你需要的是不讓host crash,最多讓guest crash。如果從API層走,那麼這件事情無法避免。如果guest里有多了個驗證,就會把錯誤留在子系統,而不會傳出來。

3. bug-to-bug兼容

如果只是API層,那麼要求guest和host的runtime完全一致,才可以保證100%兼容。而從驅動走,runtime是在guest,那麼只要都符合WDDM,就沒問題。guest和host的runtime可以解耦。

4. 什麼是驅動。

驅動不在於你怎麼實現,你是直接去真實硬體,還去了虛擬硬體。只要是按照驅動的規範實現、編譯、部署,系統看到的是個設備,那就是驅動。我給Drawbridge寫的第一版,是可以在普通的Windows上裝的,你能在設備管理器里看到多了一塊顯卡,程序可以在上面建立設備,進行渲染。(由於沒有實現電源管理的部分,在休眠後會睡死)

這裡放一張WDDM的架構圖。驅動需要實現的是user-mode display driver(UMD)和Display miniport driver(KMD)。OpenGL installable client driver屬於可選。

從這張圖也可以看到,你如果從API層面轉(也就是D3D runtime和OpenGL runtime),那麼系統並不會認為你是個設備,也沒法按照系統的規範去使用你這個設備。那就不是個驅動,也沒法實現完整的功能。

另一個嚴重問題是,GDI的部分你怎麼辦。GDI是直接調用win32k,win32k又會通過dxgkrnl去調用KMD。難道想連GDI都一起轉出來?

到了Android上,情況會更遭。Android的驅動介面和OpenGLES很像,所以從表面上看,從驅動層和從API層區別不大。但遭就遭在不同的那一點點。首先是系統有一些私有介面,只有surface flinger等android系統內會調用,而host不會有對應的。這得在驅動里解決。第二,android上的顯存管理是由驅動做的,不但host沒有對應,其他設備也會直接調用顯存管理做一些事情,比如說攝像頭。這都不可能通過API層面實現。必須提供一個驅動讓系統使用。

總的來說,比起API層,驅動層至少要有狀態管理和command list,以及可能要有顯存管理。這些,我寫的驅動里都有。

5. 如何傳輸數據

不要以為host和guest都在一台電腦,傳輸數據就很容易。圖形的東西數據量之大,API調用次數之多,都是遠遠超過其他方面的API的。還要考慮異構(CPU和GPU)上的延遲,傳輸數據這方面根本不trival。

前面提到的command list,就是一部分必做的事情。如果來一個API調用,就穿一次,即便memcpy也受不了。更好地實現是放到一個列表,只有在某些需要同步的調用下才把整個command list發送出去。我的實驗是,用和沒用,性能差6倍。另一方面是對於大塊的數據,紋理、vb,host和guest之間如何直接映射,減少拷貝而又不影響安全性,這都是得考慮的事情。

以上這幾點不光對D3D有效,對OpenGL/OpenGLES也有效。換句話說,不管什麼系統,都應該在驅動層,而不是API層做這件事情。否則死路一條。

而在CUDA方面,更難處理。因為不像D3D/OGL,texture和buffer這些都是用封裝過後的形態表示(D3D用的對象,OGL用的id),只要建立一個host和guest的映射,之後在上面的操作就能連上。CUDA裡面你可以申請一塊顯存,接著就用指針到處指了。所以需要仔細做全顯存所有權分析和數據映射。這些問題別說解決,連發現都不容易。

少年,你們仍然對力量一無所知。


浙大失敗生和杭電退學生的雙簧,我跟你們說,interesting!


驅動是一個很大的概念。在Windows里包括流驅動,類驅動。現代操作系統中分層比較多,一個事情以前可能是一個應用,一個驅動搞定;現在可能是一個驅動裡面分成很多層,每一層做每一層的事情。而且不同類型的驅動體系也不同,比如Direct的體系和藍牙,無線的體系也不一樣。

所以並不是固件,彙編才叫驅動。那麼這類問題不用太過糾結。看定義即可。


知乎技術圈就這麼幾個人,還特么整天撕逼,真是屌爆了(這不是形容詞)。


你這問題漏洞太大。Linux下哪個程序需要DirectX了?parrallels的虛擬顯卡最多只是把OpenGL調用轉發到宿主機上。Linux子系統和Windows子系統在內核看來是同等地位的。應該不需要搞這套東西才對。

不提供CUDA真正的原因肯定不是不想做。而是已經做好了,發現Linux子系統下CUDA跑分比Windows子系統下高,這就尷尬了。因為要保密,他又不能對外這麼說,只能說不想做打發你了。

-----------------------------------

以上是原答案

看到叛逆者出來胡說八道,所以恢復

顯卡驅動由兩部分組成,一部分是通過PCI介面操作硬體(以下稱為內核態驅動),另外一部分是把OpenGL調用翻譯成顯卡命令(以下稱為用戶態驅動)。

所以除了PCI-passthrough之類的獨佔顯卡的方式。一般來說,裡面支持顯卡就兩種方式,其中一種是需要在裡面安裝物理顯卡的用戶態驅動的。另外一種方式,就是主流的方式,和parallels的虛擬顯卡的原理是一樣的。主流的方式的好處就在於無論物理機用的是什麼顯卡,guest里裝的都是同一個「驅動」。把這個看作API轉發是沒有問題的,因為這個虛擬顯卡和對應的parallels tools安裝的虛擬顯卡的驅動里不會提供把OpenGL調用翻譯成GPU命令,也不會直接去操作顯卡。當然不能看作是在寫驅動了。假如這個算驅動,比如叛逆者整天吐槽AMD的驅動,他就憑這兩個案例跳槽去給AMD顯卡開發驅動,職位的級別真的能和他在微軟一樣嗎?


勃勃面前皆螻蟻啊@勃失敗


勃勃 這個問題問得好

撕起來 我看好你


推薦閱讀:

有哪些靠譜的 Ubuntu 使用教材?
Shell 是用來解決什麼問題的?
低配置的老機子適合裝哪一款Linux?
Ubuntu Kylin的核心技術體現在哪裡?
Linux 下的 C 編程有哪些值得推薦的好書?

TAG:微軟Microsoft | Linux | CUDA | 計算機圖形學 | GPU |