OpenGL如何在最低级别工作?[关闭]


84

我了解如何编写OpenGL / DirectX程序,并且了解其背后的数学知识和概念性知识,但是我很好奇GPU-CPU的通信在低级如何工作。

假设我有一个用C编写的OpenGL程序,该程序显示一个三角形并将相机旋转45度。当我编译该程序时,它将变成一系列的ioctl调用,然后gpu驱动程序将适当的命令发送到gpu,在那里旋转三角形并以适当的颜色设置适当的像素的所有逻辑都被连接了在?还是将程序编译成一个“ gpu程序”,然后将其加载到gpu上并计算旋转等?还是完全不同的东西?

编辑:几天后,我发现了该文章系列,基本上可以回答这个问题:http : //fgiesen.wordpress.com/2011/07/01/a-trip-through-the-graphics-pipeline-2011-part- 1 /


OpenGL规范规定以客户端/服务器模式发送命令。该规范范围太广,无法确定OpenGL实现所使用的特定技术。

Answers:


86

这个问题几乎是不可能回答的,因为OpenGL本身只是一个前端API,并且只要实现遵守规范并且结果符合此规范,就可以用任何您喜欢的方式来完成。

问题可能是:OpenGL驱动程序如何在最低级别上工作。现在,这通常再也不可能回答,因为驱动程序与某些硬件紧密相关,尽管开发人员设计了硬件,但它仍然可以执行某些操作。

因此问题应该是:“在OpenGL和图形系统的幕后,它的平均外观如何?”。让我们从下往上看:

  1. 在最低级别上有一些图形设备。如今,这些GPU提供了一组控制其操作的寄存器(这些寄存器确实与设备相关),具有一些用于着色程序的程序存储器,一些用于输入数据(顶点,纹理等)的大容量存储器以及通往其余部分的I / O通道接收/发送数据和命令流的系统的状态。

  2. 图形驱动程序跟踪GPU的状态以及使用GPU的所有资源应用程序。它还负责转换或处理应用程序发送的数据(将纹理转换为GPU支持的像素格式,在GPU的机器代码中编译着色器)。此外,它为应用程序提供了一些抽象的,依赖于驱动程序的接口。

  3. 然后是依赖于驱动程序的OpenGL客户端库/驱动程序。在Windows上,这是通过opengl32.dll通过代理加载的,而在Unix系统上,它位于两个位置:

    • X11 GLX模块和依赖于驱动程序的GLX驱动程序
    • 和/usr/lib/libGL.so可能包含一些与驱动程序有关的东西,用于直接渲染

    在MacOS X上,这恰好是“ OpenGL框架”。

    这是将OpenGL调用的方式转换为对(2)中描述的驱动程序部分中的驱动程序特定函数的调用的部分。

  4. 最后是实际的OpenGL API库,Windows和Unix /usr/lib/libGL.so中的opengl32.dll;这大部分只是将命令传递给了OpenGL实现本身。

实际交流的发生方式无法一概而论:

在Unix中,3 <-> 4连接可以通过套接字(是的,如果需要,也可以通过网络)或通过共享内存进行。在Windows中,接口库和驱动程序客户端都被加载到进程地址空间中,因此通信不多,而是简单的函数调用和变量/指针传递。在MacOS X中,这类似于Windows,只是OpenGL接口和驱动程序客户端之间没有分隔(这就是MacOS X如此之慢以跟上新的OpenGL版本的原因,它始终需要完整的操作系统升级才能交付新的框架)。

3→2之间的通信可以通过ioctl,读/写或通过将某些内存映射到进程地址空间,以及将MMU配置为在完成对内存的更改时触发一些驱动程序代码来进行。在任何操作系统上,这都非常相似,因为您始终必须跨越内核/用户域边界:最终,您需要进行一些系统调用。

系统与GPU之间的通信通过外围总线及其定义的访问方法进行,因此PCI,AGP,PCI-E等通过端口I / O,内存映射的I / O,DMA,IRQ进行工作。


1
该描述可能太低级,并且通用性很差,几乎没有OpenGL细节。它大致适用于计算机中存在的任何硬件组件。
v.shashenko '16

1
@ v.shashenko:当然可以。无论您要与哪个硬件组件进行通信,它都遵循此一般方案。但是OpenGL并不是特定的软件,它只是一个规范,任何符合该规范的东西都是有效的实现。而且由于最终OpenGL实现与GPU进行了对话,因此它将大致遵循与面向硬件的API相同的脚本。没有比这更具体的了,因为没有“ The ONE ” OpenGL实现。每个实现都有点不同。
datenwolf

1
@ v.shashenko:如果您想要更多细节,那么您必须询问特定的实现。例如,X11 + GLX + DRI→Mesa / AMDGPU→Linux-KMS + DRM(直接渲染管理器)。而且这些组件中的每一个都是一个非常复杂的野兽,包含许多细节,因此您可以在书中添加有关每个组件如何工作的细节。但这将描述Linux-AMDGPU的实现。但是Linux + NVidia是完全不同的野兽。在Windows上又一次不同。
datenwolf

您还记得我几天前聊天吗,我只是想知道如何与您联系,以防万一。
Suraj Jain

您那天所教的内容,消除了我的大部分疑虑,也提出了一些新观点,但总的来说,现在我不认为我们在屏幕上绘制窗口和图标是一种魔术。
Suraj Jain

23

当我编译该程序时,它将变成一系列的ioctl调用,然后gpu驱动程序将适当的命令发送到gpu,在那里旋转三角形并以适当的颜色设置适当的像素的所有逻辑都被连接了在?还是将程序编译成一个“ gpu程序”,然后将其加载到gpu上并计算旋转等?

你不远。您的程序调用可安装的客户端驱动程序(它不是真正的驱动程序,它是用户空间共享库)。这将使用ioctl或类似的机制将数据传递到内核驱动程序。

在下一部分中,它取决于硬件。较早的视频卡具有所谓的“固定功能管道”。视频卡中有用于矩阵的专用存储空间,以及用于纹理查找,混合等的专用硬件。视频驱动程序将为每个这些单元加载正确的数据和标志,然后设置DMA来传输您的顶点数据(位置,颜色,纹理坐标等)。

较新的硬件在视频卡内部具有处理器内核(“着色器”),这些处理器内核与CPU的不同之处在于它们各自的运行速度要慢得多,但还有更多的并行工作。对于这些视频卡,驱动程序准备要在GPU着色器上运行的程序二进制文件。


19

您的程序未针对任何特定的GPU编译;它只是动态链接到将实现OpenGL的库。实际的实现可能涉及将OpenGL命令发送到GPU,运行软件后备,编译着色器并将其发送到GPU,甚至使用着色器后备到OpenGL命令。图形环境相当复杂。幸运的是,链接使您摆脱了大多数驱动程序的复杂性,使驱动程序实现者可以自由使用他们认为合适的任何技术。


17

C / C ++编译器/链接器仅做一件事:它们将文本文件转换为一系列在CPU上运行的特定于机器的操作码。OpenGL和Direct3D只是C / C ++ API。他们无法将您的C / C ++编译器/链接器神奇地转换为GPU的编译器/链接器。

您编写的每一行C / C ++代码都将在CPU上执行。调用OpenGL / Direct3D会调用C / C ++库,视情况而定是静态的还是动态的。

“ gpu程序”起作用的唯一地方是您的代码明确创建了着色器。也就是说,如果您对OpenGL / D3D进行API调用,从而导致着色器的编译和链接。为此,您(在运行时,而不是C / C ++编译时)可以生成或加载以某种着色器语言表示着色器的字符串。然后,将它们推入着色器编译器,并在该API中获取一个代表该着色器的对象。然后,您将一个或多个着色器应用于特定的渲染命令。这些步骤中的每一个都明确地按照C / C ++代码的方向进行,如前所述,该代码在CPU上运行。

许多着色器语言都使用类似C / C ++的语法。但是,这并不等于C / C ++。


我最近一直在学习opengl,并且想知道为什么我在以乱码形式编写的代码中看到了所有这些“着色器程序”。如您所说,它们是在运行时编译的。我在一些android opengl es代码中看到了一些示例。然后我也看到了一些iPhone的代码。显然,iPhone具有四个向量处理器,它们能够比iPhone的CPU更快地执行浮点运算-因此,您可以将ASM编写为文字字符串,以便在运行时进行编译以使用这些处理器而不是主CPU。
eggie5 2011年

1
现在,大多数“固定功能管道”都是由默认的着色器程序集实现的。您无需显式请求着色器即可获得一个。
Ben Voigt

1
@Ben Voigt:是的,但是如果没有人告诉您,您将无法说出区别。
Nicol Bolas

1
如果这个问题不是关于隐藏的细节,那可能是明智的态度。
Ben Voigt
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.