• 计算机图形学底层知识


    一、底层知识背景

    1.1 GPU和CPU的区别?

    主流 CPU(Central Processing Unit,中央处理器)芯片上有四级缓存,消耗了大量晶体管,在运行时需要大量电力;主流 GPU(Graphics Processing Unit,图形处理器)芯片最多有两层缓存,且 GPU 可以利用晶体管上的空间和能耗做成 ALU 单元,因此 GPU 比 CPU 效率高。

    CPU 重在实时响应,对单任务速度要求高,需要针对延迟优化,所以晶体管数量和能耗都需要用在分支预测、乱序执行、低延迟缓存等控制部分;GPU 主要使用于具有极高可预测性和大量相似运算的批处理,以及高延迟、高吞吐的架构运算,对缓存的要求相对很低,顺序运算效率很高,同时相对的乱序处理效率很低。

    CPU 除了负责浮点和整型运算,还有很多其它的指令集的负载,如多媒体解码和硬件解码,CPU 注重单线程性能,保证指令流不中断,需要消耗更多晶体管和能耗用在控制部分,于是 CPU 分配在浮点运算的功耗会减少;GPU 基本只进行浮点运算,设计结构简单,效率更高,GPU 注重吞吐率,单指令能驱动更多的计算,相比较 GPU 消耗在控制的能耗就少得多,因此可以将资源留给浮点运算使用。GPU 的浮点运算能力比 CPU 高 10~12 倍。

    1.2 什么是NVIDIA/AMD?

    显卡品牌。NVIDIA 公司译为英伟达,其生产的显卡又被称为 N 卡。AMD 译为超微半导体,其生产的显卡又被称为 A 卡。

    N 卡奉行大核心战略,GPU 内部采用大量 1D 单元,在执行效率上理论可以达到 100%,实际效率也可以维持在 90% 以上,因为架构执行效率高,灵活性强,所以在实际应用中易发挥应有性能。但是大核心的设计复杂,成本和功耗也会比较高。N 卡在软件上具有明显优势,包括微软在内的软件商都为 N 卡开发优化,使得大量工具软件和游戏在 N 卡环境下有更好的表现。

    A 卡奉行小核心战略,采用 VLIW5 或 VLIW4 的设计,分别采用 4D+1D 的设计和 4D 设计,可以在较小的晶体管代价和较小的核心面积下装入更多的 SP,以 SP 的数量取胜。其理论计算能力远超 N 卡,但实际执行效率并不高,一旦进入 GPU 的图形信息是 1D 或 3D 形式这一的非标准数据形式,A 卡的执行效率最低可降至 25% 至 20%。

    1.3 GPU和显卡有什么关系?

    GPU 是显卡上的核心处理芯片,显卡上除了 GPU,还包括显存、电路板和 BIOS 固件等。由于 GPU 在显卡上十分重要,所以时常用 GPU 代指显卡。

    显卡也叫显示适配器,分为独立显卡和集成显卡。独立显卡由 GPU、显存和接口电路组成;集成显卡和 CPU 共用风扇和缓存,没有独立显存,而是使用主板上的内存。

    1.4 什么是流处理器SP?

    流处理器又称流处理单元,简称 SP单元(Streaming Processor) 或 SPU,有些显卡生产商也会将其称作 core(核心)。流处理器的数量能直接影响显卡性能。

    之前的显卡具有两个重要的运算单元——顶点处理单元和像素处理单元。但自从 DirectX10 开始,微软引入了流处理器这个概念,顶点处理单元和像素处理单元很快被业界抛弃。流处理器是顶点处理单元和像素处理单元的统一,负责了渲染中的顶点和像素渲染。将顶点处理单元和像素处理单元合并的概念又被称作统一着色器架构(Unified Shader Architecture)。

    业界之所以抛弃之前的顶点+像素结构而使用 SPU 架构,是因为传统的顶点和像素分离渲染架构存在严重的资源分配不均的问题,两种单元渲染任务量不同,效率低下。而 SP 架构是统一结构,不再区分顶点和像素渲染,进行不同渲染任务时都能保证效率。

    1.5 4D+1D/4D/1D都是什么?

    D 是维度 Dimension 的意思,在图形学中的 nD 指 n 维浮点向量运算,nD 单元指由 n 个流处理单元整合成的 n 维浮点向量运算单元。

    像素坐标 XYZW、色彩参数 RGBA 以及纹理坐标参数 STPQ 正好都是 4 维运算,这导致顶点处理单元和像素处理单元都是 4D 单元,在引入流处理器后,主流的流处理器也是 4D 单元。

    而 1D 即一维向量,也就是标量。由于流处理器合并了顶点和像素处理单元,图形渲染中标量运算成分开始增多,GPU 不再像早年那样只需要处理单纯的 4D 向量运算了。在这样的背景下,英伟达完全抛弃 4D 结构,设计了 G80 这样的 1D 标量处理器,将矢量运算分解为 4 次或更多次标量运算,这使 N 卡的灵活性大幅提升,在任意维度的运算环境下都可以得到满意的性能。

    AMD 没有放弃 4D 架构,而是进行了改良,增加了一个标量运算单元,这就是 4D+1D 矢量标量混合架构,也就是 VLIW5(Very Long Instruction Word,超长指令口令)架构,它把需要计算的指令组合成适合 4D+1D 架构的长指令,比如将一个 2D 运算和一个 3D 运算合并为一个 4D+1D 运算,这样理论上每个统一处理器每个周期都可以进行一次 4D 运算加一次 1D 运算,是 N 卡 1D 单元运算效率的 4~5 倍,这种将指令组合的算法被称为 co-issue 算法。这五个 ALU 只需要一个发射端口,电路设计更加简单,功效与发热也更容易控制,但缺点就是依赖指令组合,一旦非最优指令组合,这些运算单元中部分维度就只能空转,运算效率将显著降低。

    1.6 什么是显卡驱动?

    一个应用程序向显卡接口发送渲染命令,这些接口会依次向显卡驱动发送渲染命令。显卡驱动的地位类似于 C 语言编译器,可以将 OpenGL 或 DirectX 的函数调用翻译成 GPU 能读取的机器指令,即二进制文件。显卡驱动同时也负责把纹理等数据转换成 GPU 支持的格式。


    二、图形API和着色语言

    2.1 什么是OpenGL/DirectX?

    图像编程接口(图形 API),是对 GPU 硬件的抽象,其地位类似 C 语言,属于 GPU 编程的中低层。几乎所有 GPU 都既可以和 OpenGL 合作也可以和 DirectX 合作。


    2.2 什么是HLSL/GLSL/CG/CUDA?

    HLSL、GLSL 和 CG 是着色语言,专门用于编写着色器。其中 HLSL(High Level Shading Language)属于 DirectX,GLSL(OpenGL Shading Language)属于 OpenGL,而 CG(C for Graphic)是 NVIDIA 研发的,因为英伟达与微软合作密切,CG 语法与 HLSL 极其相似。

    CUDA(Compute Unified Device Architecture,统一计算架构)也是 NVIDIA 研发的,和前三者类似,但并不专注于图形领域,常用在机器学习等领域,不需要像着色语言那样使用图形计算的逻辑进行数字运算。

    三、Draw Call

    3.1 什么是Draw Call?

    调用一次图像编程接口(图形API),以命令 GPU 进行渲染的过程就称为一次 Draw Call。


    3.2 Draw Call的流程是什么?

    Draw Call 的准备工作由 CPU 完成。

    第一步,CPU 把一个网格的顶点数据从硬盘中加载到内存中(存在这一步的原因是大规模3D渲染中内存可能不足)。

    第二步,CPU 对这个网格设置渲染状态(每个网格不等于每个模型/图片,因为存在批处理)。所谓渲染状态包括纹理贴图、材质属性和被编译为二进制文件的着色器。随着渲染状态一起被传递到 GPU 的还有光照和摄像机相关的信息。图形 API 可以更深层次的定义渲染状态需要的数据。

    第三步,CPU 将网格顶点数据与渲染状态打包,将数据包按照指定格式交给 DMA,由 DMA 将数据包传入显卡。

    显存完成接受数据包后,DMA 向 CPU 返回一个中断信号,Draw Call 正式结束。

    3.3 GPU是如何接受Draw Call的?

    指令到达显卡驱动程序后,驱动会首先检查指令的合法性,如果指令非法,驱动会通过 DMA 向 CPU 发送错误信息。如果指令合法,驱动通过 DMA 确认 Draw Call 接收,然后将指令放入 GPU 缓冲。

    一段时间后当显卡中存在空闲流水线,或者 CPU 显式发送 flush 命令后,驱动程序把缓冲区中的一份指令发送给 GPU,GPU 通过主机接口接受命令,并开始处理命令。

    GPU 将所有顶点存入顶点缓冲区(Vertex Buffer),GPU 中的图元分配器(Primitive Distributer)开始通过顶点生成三角形,并将他们分成批次(batch),发送给一个或多个 GPCs,如果显卡不存在 GPCs,则直接分发给 SM。SM 获得数据后,束管理器安排多边形引擎将三角形数据提取出来存入 SM 的 L1 缓存,随后开始顶点着色器阶段。

    GPU 会依次处理缓存中的每一个网格,网格的处理顺序与 CPU 的提交顺序有关。正因如此,CPU 总是最后提交透明物体。等一帧中的所有 Draw Call 处理完毕后,显示器才会将图像打印在屏幕上。

    3.4 什么是批处理?

    对 2D 物体(UI)来说,如果两个或多个 UI 元素符合以下条件则可以被批处理:

    • 使用相同的材质与纹理,即使用相同渲染状态。
    • 这些元素的层级相同,或这些元素之间不夹杂使用其它渲染状态的元素的层级。

    对网格(模型)来说,如果两个或多个网格符合以下条件则可以被批处理:

    • 使用相同的材质与纹理,即使用相同渲染状态。
    • 顶点总数不超过一个阈值,该阈值大小与使用的处理引擎有关。

    3.5 为什么要进行批处理?

    Draw Call 的性能瓶颈是 CPU 而非 GPU。CPU 每进行一次 Draw Call,都要调用一次 DMA 将数据输入显存。在每次调用时,对显存的映射寻址、DMA 控制块的注入、等待 DMA 响应等系统消耗都会浪费时间周期,多次进行 Draw Call 就会有多次消耗。同时,DMA 擅长一次传输大量数据,而不擅长多次传输少量数据。这使得降低 Draw Call 对于优化显示性能很有必要。

    批处理可以显著降低 Draw Call。通过将类似的网格当作同一网格,CPU 可以在一次 Draw Call 中将更多的数据传输到 GPU 中,降低系统消耗。

    四、渲染流水线

    渲染流水线是在显存中开启的。CPU 将网格、材质、贴图、着色器等注入显存后,GPU 开始渲染流水线。

    渲染流水线分为几何阶段和光栅化阶段(也被称为像素阶段),并最终将运算结果送到显示器的缓冲区中。

    几何阶段分为顶点着色器 -> 曲面细分着色器(DirectX11 和 OpenGL4.x 以上可编程) -> 几何着色器 -> 裁剪 -> 屏幕映射五个步骤。

    光栅化阶段分为三角形设置 -> 三角形遍历 -> 片元着色器 -> 逐片元操作四个步骤。

    显卡厂商会通过硬件实现常用且功能变化不大的几个流水线阶段,因为通过硬件实现的效率远高于软件实现。这些阶段优的根据 API 的设计,提供了一些可以设置的参数,但总的来说不会脱离 GPU 的控制。

    在这个过程中我们可以知道,顶点着色器和片元着色器的线程数并不是等同的。片元着色器的线程数变化幅度一般不大,而顶点着色器的线程数变化幅度随应用不同可能大幅浮动。

    参考:

    图形学基础概念笔记(一)


  • 相关阅读:
    19. Remove Nth Node From End of List
    18. 4Sum
    16. 3Sum Closest
    15. 3Sum
    17. Letter Combinations of a Phone Number
    A Network-based End-to-End Trainable Task-oriented Dialogue System
    14. Longest Common Prefix
    36. Valid Sudoku
    29. Divide Two Integers
    32. Longest Valid Parentheses
  • 原文地址:https://www.cnblogs.com/linuxAndMcu/p/14483139.html
Copyright © 2020-2023  润新知