大家好,又见面了,我是你们的朋友全栈君。
背景
本次使用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)其他问题,记不住了,反正还有好多问题,后面再补充。。。。。
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/171781.html原文链接:https://javaforall.cn