计算机底层是如何访问显卡的

作者:谷俊
链接:https://www.zhihu.com/question/20722310/answer/24824346
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

其实你可以把显卡想象成另外一台机器。那么控制另外一台机器的办法,就是往它的内存里面写指令和数据。往一块内存里面写东西的办法无非就几种,1, 用CPU去做,那么就是用MMIO(Memory Mapped IO)把'显存' map到CPU寻址空间,然后去读写,2, 用DMA控制器去做,这里面有系统自带的DMA控制器或者显卡带的,不管哪种你可以把DMA控制器再一次看作另外一台机器,那么其实就是向DMA控制器写指令让它帮你传一些东西到显存去,传的这些东西就是显卡要执行的命令和数据。显卡上的内存控制器,原来AGP的时候叫GART,现在不知道叫啥名了,另外SoC里面也有类似的概念,不过大多数SoC只有一个内存控制器,所以不分显存和内存。

把显卡想象成另外一台机器。它要工作,无非也是“程序存储”原理,上电之后,从特定的内存(显存)地址去取指,然后执行指令。显卡的工作逻辑比CPU简单多了,它一般就从一个环形buffer不断的取指令,然后执行,CPU就不断的去往环形buffer填指令。

很多时候同一个动作既可以用MMIO,也可以用DMA,比如flip framebuffer。只要把flip framebuffer的指令正确传到环形buffer就好了。但是MMIO需要CPU参与,传大数据的时候,打乱CPU GPU并行性,划不来。

驱动程序其实也是围绕着这件事情来做的,Vista以前,显卡的驱动全都是kernel mode执行的,因为只有kernel mode才能访问的物理地址,但是kernel mode的坏处是一旦有问题,系统就崩溃,而且kernel mode有很多局限性,比如没有C库支持,浮点运算很难,代价很大等等。所以Vista之后,显卡驱动都分两部分,kmd负责需要访问物理地址的动作,其他事情都放到umd去做,包括API支持等等。所以一个3D程序执行的过程是这样的,app generate command, call D3D runtime,D3D runtime call driver umd, driver umd system call driver kmd, kmd send command to ring buffer, graphic card exeute.

至于显卡驱动要完成什么部分,这个就是所谓HAL(hardware abstraction layer)层,也就是说HAL以下由厂商提供,以上就是操作系统自带,在HAL层以上,所有的操作都是统一的,比如画一个点,画一条线,驱动来对应具体的某一款芯片生成真正的命令,比如画点,需要0x9指令,把绝对坐标放到地址0x12345678(举例)。微软管的比较宽,umd, kmd都有HAL层,意思是即使kmd你也不能乱写,能统一的尽量统一,比如CPU GPU external fence读写同步机制就是微软统一做的。

流处理器就是说,那些处理器可以执行很多的指令,而不是就几个固定的功能,比如原来我把几个矩阵的乘法固定成一个操作(比如T&L单元),现在我把这个操作拆了,改成更基本的指令,比如,取矩阵元素,加乘,这样更灵活。不过你就得多费心思去组合这些指令了,组合这些指令有个高大上的名字,shader。至于为什么叫shader,越来越长了,不说了。

你可能感兴趣的:(汇编语言)