关于
本来计划写一篇博客梳理整个渲染流程,但写着写着就发现一篇博客根本没法囊括我所有想要梳理的东西,所以就只能分成很多篇来写啦。这篇主要是准备写一下相关的硬件设施,即 CPU、GPU 和显示屏在这整个渲染流程中所起的作用,他们之间的通信方式,以及他们分别对渲染流程的影响。
CPU
CPU 主要负责一些数据的预处理。这些处理可以由开发者全权掌握。首先,CPU 会从文件或代码中获得需要渲染的内容,如模型的顶点位置信息、贴图坐标、法向量等信息。根据用户/程序员的输入小方块相对世界坐标的位置,相机的各项信息,纹理的图片文件,以及其他任何相关信息。在软件的运行过程中,CPU 会逐步将对应的数据存入 buffer(显存)中,并指定其 ID,以方便 GPU 读取。
此外,CPU 还控制着每一帧的循环。在每一帧开始渲染之前,CPU 需要指定 shader 中每一个参数对应在 buffer 中的 ID。同时,所有逐帧变化的参数(如位移或旋转)也会由 CPU 进行计算,并在循环中更新 buffer。有时为了优化渲染、减轻 GPU 压力,CPU 还会进行一些其他计算,如剔除看不见的元素,只要求 GPU 渲染当前可见的物体。在所有数据准备妥当以后,CPU 会发布渲染指令(draw call),要求 GPU 渲染指定的物体。
图形 API
图形 API 是 CPU 和 GPU 交互的接口,以及 shader 的编译器,不同的图形 API 有不同的 shader 语言。但总体而言,程序员可以调用图形 API 来指定 GPU 相关流程的处理方式、显存和计算单元的交互等。
GPU
GPU 是计算机处理图形的主要硬件。它约等于我们平时所说的显卡(Graphics card),但其实 GPU 和显卡还是有一些区别的。显卡包括了散热器、通讯元件、各种插槽等等,而 GPU 是显卡的核心部分,即存储和计算单元。相比 CPU,GPU 拥有更多的算数运算单元(ALU),更少的内存和控制单元(负责内存交互、将计算结果传输给另一个计算单元等)。因此 GPU 更擅长大规模并行计算,而十分不擅长处理复杂的逻辑控制单元。此外,GPU 无法进行分支预测,因此需要尽可能避免在 GPU 中处理分支结构(即 if、else)。
在图形处理中,GPU 主要负责像素点的颜色计算。通常来说,CPU 将所有处理好的信息(如物体位置、变换矩阵等)存入 buffer。GPU 的控制单元可以一次性读取所有相关数据,分别传入不同的计算单元,使得这些计算单元可以同时进行计算以同时得到不同像素点的颜色信息,从而快速算出每一帧的信息。但 GPU 的处理步骤并非全都是可编辑的。传统情况下只有处理点的 vertex shader 和处理像素的 pixel shader 会开放给程序员编辑。虽然现代图形 API 在逐步开放更多下步骤,比如编辑几何体的 geometry shader。
在经过一系列操作后,GPU 会将最终完成的画面存入显存中,再将这个画面设置成显示区,将原来的显示区交换到后台区等待下一次写入和交换。这样就避免了画面部分完成时前后帧割裂。在渲染好的画面传到显示器后,会有 DAC Digital Analog Convertors 将数字信号转化成模拟信号再由显示器最终输出。
显示器
显示器是画面最终呈现的地方。最早是 CTR 显像管,LCD 液晶,到现在街上最常见的 LED 发光二极管显示屏,还有基于 LED 的常用于智能设备的 OLED 和电视常用的适合大屏的 MiniLED 等等。至今为止,显示器都是通过点阵列来展示图像的,一个光点就是一个显像设备,通过不同光点不同颜色和亮度来拼凑成完整的图像,光点就是我们常说的像素,光点数量就是我们常说的分辨率。显示器的性能限制了画面最终呈现的效果。低分辨率的显示器没法显示高分辨率的画面,光点的显色范围和刷新速度也限制了画面的最佳效果。
渲染的光栅化步骤就是为了将画面转换为显示器可以接收的点阵列。光栅化的时候可以设定分辨率,决定最终输出的视频占多少像素。若输出像素数量小于显示器像素数量则是非全屏显示,若输出像素数量大于显示器分辨率则画面会超出屏幕。
参考资料
- 知乎 - 为什么深度学习和神经网络需要GPU?
- 知乎 - 深入理解CPU的分支预测(Branch Prediction)模型
- 知乎 - 2024年显示器推荐及避坑选购指南
- 知乎 - CPU是如何处理图像信息并将图像显示到屏幕的