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

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




  

相关话题

  华为 Linux 内核贡献者被质疑刷 KPI,真实情况是怎样的?有哪些信息值得关注? 
  教材上说铁路订票系统是实时操作系统,可是服务器的Linux不是分时操作系统吗? 
  Minecraft 会以什么方式没落? 
  如何看待微软 Build 2019 上发布的新 WSL2? 
  微软公司对人类造成了什么影响?如果没有微软,人类现在会是怎样的生活? 
  鸿蒙之于AOSP,是否Linux之于wine,Windows之于WSL?这么多人质疑鸿蒙说明了什么? 
  为什么企业微信没有Linux版本? 
  如何正确的入门Vulkan? 
  如何看待微软公开 exFAT 文件系统细节,并宣布向 Linux 开源? 
  Windows 的文件夹的权限管理为什么乱七八糟的? 

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





© 2024-06-18 - tinynew.org. All Rights Reserved.
© 2024-06-18 - tinynew.org. 保留所有权利