百科问答小站 logo
百科问答小站 font logo



龚神给微软 Linux 子系统写的支持 DirectX 9、11的代码到底属不属于“驱动”? 第1页

  

user avatar   minmin.gong 网友的相关建议: 
      

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

首先,问题是错的。我在另一个帖子里

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里面你可以申请一块显存,接着就用指针到处指了。所以需要仔细做全显存所有权分析和数据映射。这些问题别说解决,连发现都不容易。

少年,你们仍然对力量一无所知。




  

相关话题

  为什么库克说 iPad Pro 可以取代 Windows 台式机和笔记本电脑? 
  为什么我们用微软的系统这么多年,遇到问题第一时间是谷歌百度,而不是找微软售后服务? 
  如果 Windows 系统全套源代码(技术文档)泄漏,会发生什么? 
  字节跳动拒绝微软收购 TikTok 美国业务,这意味着什么? 
  魔兽世界虎年你最想要什么坐骑? 
  一台用于学习linux的主机该如何配置、选购? 
  苏州微软 Bing 团队与杭州阿里妈妈广告推荐引擎开发岗位应该选哪家 offer? 
  如何看待明尼苏达大学因插入实验性漏洞,被禁止贡献 Linux 内核代码? 
  Linux 出于何种考虑推出 usrmerge,将根目录下的一些文件夹合并到 /usr 下? 
  如何评价 Surface Book 变形式笔记本电脑? 

前一个讨论
2016 年诺贝尔经济学奖得主的契约理论对于国企改革有哪些借鉴意义?
下一个讨论
macbookpro 2016 15寸低配版 和 mbp 2015 高配 如何选择?





© 2024-12-22 - tinynew.org. All Rights Reserved.
© 2024-12-22 - tinynew.org. 保留所有权利