win7下虛擬顯示器完成記(virtual monitor)——VDI顯卡透傳場景

背景

本次使用wddm過濾驅動的應用場景是VDI GPU透傳場景,我這邊運用WDDM過濾驅動,也有人叫wddm hook,主要有如下功能:

(1)給透傳顯卡虛擬出一個顯示器,因爲透傳顯卡都是插在服務器上,一臺服務器需要插十幾張顯卡(消費級顯卡),不可能給每個顯卡插一個顯示器,不插顯示器又會存在分辨率無法設置,分辨率過低的問題,爲此需要自己虛擬一個顯示器“插”在透傳顯卡上。

(2)我們VDI使用spice協議,spice協議的圖片來源是QXL顯卡驅動,現在QXL顯卡被透傳顯卡取代了,QXL驅動沒有了用武之地,如果此時想使用spice協議進行連接,可想而知,結果就是黑屏,問題是如何在不改變spiceserver和spiceclient代碼的情況下實現spice的正常連接,這也需要依賴wddm過濾驅動了,此次它提供的功能是高效採集屏幕信息,需要採集每次變化的區域(全屏採集的話會造成帶寬劇增)。

 

進展

將近3個月過去了,一直在做win7下虛擬顯示器的相關工作,本次幾個比較大的收穫:

(1)是實現了虛擬顯示器對Aero效果的支持,在Intel集顯、AMD和NV獨顯有分別做過測試,都能做到較好的支持(更細緻的型號支持,需要進一步接受市場考驗);

(2)通過WDDM過濾驅動實現了win7下的高效截屏,同時能獲取到屏幕變化區域;

(3)突破了在windows7上對Aero效果高效截屏和D3D全屏(獨佔模式)的高效截屏,其中D3D全屏的截屏相對於OBS的HOOK API方案,具有更好的兼容性,同時具備更高效率。

  最終實現的效果如下:PC上插一個物理顯示器,自己虛擬一個顯示器,左邊顯示爲虛擬顯示器內容,通過一個軟件來看效果,右邊是物理顯示器,以下是讓虛擬顯示器和物理顯示器呈現“複製屏”模式和“擴展屏”模式。

意義:

(1)該實現意味着我們可以在VDI上使用消費級顯卡透傳到虛機,作爲渲染引擎,不再依賴專業級顯卡,不再依賴顯卡廠商爲我們提供拔插虛擬顯示器API、截屏API,對成本的降低可想而知!

(2)在VDI上對vGPU場景、顯卡透傳場景可以使用同一套顯示框架,且無需去關注GPU是哪個廠商,會大大降低開發工作量!

考慮到很多網友只對虛擬顯示器感興趣,所以特別搞了個虛擬顯示器的demo:

https://blog.csdn.net/dailongjian2008/article/details/80958163

後續會推出專門用於截屏的wddm hook框架的demo,具有強大的兼容性,適應各類顯卡,敬請期待......

  10月份我請了陪產假,老婆生了個漂亮的女兒,我也是兒女雙全了,也有半個月的時間沒有上班,在家的那段時間,仔細梳理了下實現邏輯以及下一步應該側重的方向,好讓我11月份上班後的嘗試不再那麼的沒有針對性。所以我11月份一上班便很快取得了一些突破。

  虛擬顯示器我在7月份的時候做完了,下一步要做的就是把虛擬顯示器的屏幕數據截獲並遠程傳遞給客戶端顯示,做完後爲了更快的看到效果和進行試點,最開始我獲取屏幕數據採用mirror驅動方式, mirror驅動是win7上微軟官方支持的效率最高的截屏方式,win7在截屏這塊其實是比較尷尬的,mirror驅動是XP時代的產物,在win7上使用起來有太多的限制,DXGI方式的截屏只能在win8及以上系統使用。

  從測試和試點的效果來看,使用mirror驅動截屏目前來說有幾個比較顯著的缺點:

(1)只能截獲主屏數據,擴展屏貌似不能截(不清楚怎麼截擴展屏,有知道的可以告知聲);

(2)開啓了mirror驅動win7就不能開啓毛玻璃效果,且DirectDraw加速之類的不能使用,大大降低了體驗;

(3)對D3D全屏場景,如3D遊戲全屏,Media Center全屏,Mirror驅動是截不到的,具體原因我這裏就不多講了,可以自行研究;

(4)在測試過程中發現有些場景,如PS的畫圖場景,開啓硬件加速後,只要有開啓mirror驅動,延時就會變得相當嚴重,開始以爲是我們mirror驅動實現的問題,後面直接把微軟的sample拿過來,什麼都沒改,開啓後延時依然,這樣的話證明延時就跟就跟mirror驅動的框架有關了。

  鑑於上述的種種原因,在開發完mirror驅動截圖一個版本後,我決定放棄這種框架,因爲後面的維護成本會很高,而且有很多硬傷是無法解決的,倒不如拋棄這種框架。於是我決定去嘗試直接從wddm過濾驅動獲取圖片數據,其實displayLink驅動的截圖就是這種實現的,他們的效果是業界一流的。

  從9月份一開始我就轉入了WDDM過濾驅動截獲圖片數據開發,先從支持非Areo效果的圖片開始,期間也遇到了很多問題:

內存映射問題

(1)如何獲取虛擬顯示器surface地址?地址如何轉換成我們可以訪問的虛擬地址?

(2)如何獲取圖片更新區域?

(3)如何獲取鼠標形狀、位置?

  爲此我們需要閱讀微軟官方的資料:https://docs.microsoft.com/en-us/windows-hardware/drivers/display/video-memory-management-and-gpu-scheduling

  內容比較多且比較抽象,但是是我們能找到的最好的教程,所以要耐心看完。

拷貝速度慢問題

  做了1-2個星期,幾乎把WDDM文檔都看爛了,上面列舉的這些問題大都解決了,我可以在WDDM過濾驅動獲取到我想要的圖片信息了,並且可以對顯卡的Framebuffer進行修改了,比如給屏幕加個水印什麼的(是不是很高大上!!!)。

  本以爲大功告成,等待收穫勝利的果實了,沒想到不久就面臨一個棘手的問題:拷貝速度慢問題,地址映射完後,我們是可以獲取到FrameBuffer的虛擬地址的,也就是說我們可以直接讀取FrameBuffer,這樣一來直接從Framebuffer截屏就顯得很方便了,但是不幸的是,直接從FrameBuffer將數據拷貝出來耗時相當大,我這邊統計了下,拷貝一張1080P的圖片大約在90ms左右,這是一個相當大的耗時,在實時傳輸上根本沒法用,沒辦法,只能繼續解決這個頭疼的問題,主要的一個思路是激活顯卡的DMA傳輸,讓它幫忙拷貝。

其他問題

  我這裏支持介紹了個大概,如果有開發這類遇到問題可以留言諮詢,我會盡力解答,開發這個東西遇到的坑是相當相當多的,我一直堅信,別人(displaylink)能實現,開發過程中遇到的任何問題肯定是有解決方法的,所以在出現各類奇怪問題的時候我中途沒有放棄,一直在堅持,也堅持到了最後。後面會陸續遇到:

(1)毛玻璃效果開啓後虛擬顯示器不支持,會一直狂閃然後藍屏;

(2)在Intel集顯上Mediacenter在擴展屏上顯示不了,出現黑屏、閃屏問題;

(3)在AMD顯卡上,一些播放器,如Potplayer在擴展屏上播放視頻,幀率會比較低;

(4)在AMD顯卡上測試顯卡幀率的網站,在物理顯示器上運行,有60幀,在擴展屏上運行時,降到不到10幀;

(5)Furmark測試顯卡性能,在擴展屏上相當卡頓,上面說的卡頓問題都是不同的問題,解決完一個另一個還是有的,要分別解決;

(6)PS硬件加速開啓,在物理顯示器上很流暢的畫圖,在擴展屏上延時很重;

(7)各類藍屏問題;

(8)其他問題,記不住了,反正還有好多問題,後面再補充。。。。。


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章