天天看點

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上插一個實體顯示器,自己虛拟一個顯示器,左邊顯示為虛拟顯示器内容,通過一個軟體來看效果,右邊是實體顯示器,以下是讓虛拟顯示器和實體顯示器呈現“複制屏”模式和“擴充屏”模式。

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

意義:

(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)其他問題,記不住了,反正還有好多問題,後面再補充。。。。。

繼續閱讀