当前位置: 首页 > news >正文

OpenGL-ES 学习(12) ---- GPU 系统结构

目录

      • 图形流水线
      • GPU内部构成
        • Job Manager
        • Tiler
        • ShaderCore
        • No-Fragment Front-end
        • Fragment Front-end
        • ExcutionCore
        • Warp Manager
        • ExcutioEngine
        • Load Store unit
        • Varying Unit
        • Texture unit
        • Fragment Back-end
        • Memory-port

图形流水线

一个图形应用是以流水线的方式运行,如下图所示:
图形流水线.png

CPU 负责向 GPU 提交 Render Operation,包括设置管线状态,准备渲染数据,提交绘制命令(也就是draw call)
GPU 负责对渲染数据进行计算,对于不同的 Render pass,可以以流水线的方式并行执行
OpenGL-ES 的渲染管线流程如下图所示:
OpenGL-ES 图形管线.png

顶点着色器:顶点着色器的输出称为可变变量(Varying),顶点着色器还可以实现矩阵变换位置、计算照明公式来生成逐顶点颜色,生成或者变换纹理坐标等基于顶点的操作

图元装配:图元是指三角形,线段,或者点等几何对象,图元的每个顶点被发送到顶点着色器的不同拷贝,在图元装配期间,这些顶点被装配成图元;每个图元,还需要确认图元是否位于视锥体内,如果没有完全位于,就需要进行裁剪,或者直接剔除,裁剪和剔除之后,顶点位置就被转换为屏幕坐标,传递给管线的下一阶段进行光栅化

光栅化:光栅化是将一组图元转换为一组二维片段的过程,输出屏幕坐标,颜色,纹理坐标等然后,这些片段由片段着色器处理,这些二维片段代表着可以在屏幕上绘制的像素

片段着色器:片段着色器输出一个颜色值

渲染流程如下:

  • 首先图形应用输入顶点的值,再将这些顶点构成成基本图元(三角形)
  • 三角形的每个顶点经过 VertexShader 处理,被变换到 Clip space中,然后再做透视投影被投影到 View space 中,
  • 经过视锥裁剪被背面剔除之后,剩下的三角形都被 Tiler 处理,得到每个 Tiler 上的 polygon list(polygon:多边形),
  • 然后就是光栅化(Rasterzation)、early-ZFPKFragmentShaderz testblend 等一系列流程,执行完成之后就可以得到一个有用的 pixel,并且被写入 FrameBuffer

GPU内部构成

Job Manager
  • CPU 提交的绘制命令,会首先由 JobManager 进一步拆分,将 VertexShaderFragmentShader 分别提交到 Non-FragmentSlotFragmentSlot 这两个队列中(Vulkan 中有直接获取队列的操作),绘制命令中也有可能包含 Compute Shader,同样也是进入 Non-FragmentSlot 中进行处理
  • 然后 ShaderCoreFrontEnd 就会创建对应的 Warp 来执行任务 Warp: 一组锁步执行的线程(实际就是SIMT的实现),在 Valhal 架构中,一个Warp 包含十六个线程,Mali-G52 GPU 一个Wrap 包含8个线程
Tiler

TilerTBR(Tiler based rendering) 架构中固定的功能,用于将 Framebuffer 切成小tile,为每个 Tile 生成相应的 polygon list. Tile 是将一个完整的FB切分形成16x16 大小的小型FB,Tiler 之后的操作都是在这个 16x16 大小的Buffer 上进行的,直到这一帧所有的 Tile 都绘制完成,原本的 FB 才会拼装完成,送到显示系统
PC上常用的 IMR(Immediate Mode Rendering),流程如下
IMR.png
好处是基本数据被填充到 FIFO里,随取随用,即使几何数据再多,也不会累计在片上内存,缺点也是显而易见的,这些几何数据可能被光栅化到 FB 的任何位置,所以在执行 FragementShader 的时候读取 FB 容易造成 cache 失效导致很大的 DDR 带宽,比如 blenddepth test,对于移动设备,访问 DDR 的代价是非常昂贵的
TBR (Tile based Rendering) 使用小型 FB 优化了这个过程
TBR.png
因为 Tile 很小,可以在 GPU上分点地方放它,对于FB的频繁访问,不再产生DDR带宽,而是变成了低时延,低功耗的 Tile 访问;同时在写出之前,对上次 Tile 中的结果进行 CRC 校验,使得相同的内容不再写,又可以节约更多的带宽

ShaderCore

Shader CoreGPU中最核心的部分,是执行 Shader 的器件,之前的 GPU 部件,我们能编程控制的很少,但是 Shader Core 基本完全掌握在我们手中,ShaderCore 包含在处理之前进行处理的 Front-End,执行 Shader 指令的 ExcutionCore ,对 FragmentShading 结构做进一步操纵的 Back-end 三个部件
Shadecore1.png

No-Fragment Front-end

No-Fragment Front-end 负责处理非Fragment 执行之前的操作,负责创建 Warp,包含 Vertex ShaderCompute Shader,创建 Wrap 的过程包含寄存器分配

Fragment Front-end

Fragment Front-end 的流程比较复杂,在 FragmentShader 执行之前,数据还是保存在 DDR 里的 PolygonList,距离变成需要执行 ShaderFragment,还需要经过下面流程:
ShaderCore.png
首先必须从 DDR 中将一个 Tile 对应的 Polygon List 读取到 GPU上,然后再进行光栅化,对三角形进行采样,以及对顶点属性继续插值,之后为了缓解 overdraw(像素被之后的像素阻挡),进行了early-ZFPK 对一些无效的 Fragement 进行剔除,剩下的被 FragemnetShader 处理
这里可以看出

//Non-fragment queueActive = Non-fragemnt jobslot active + Tiler Active + Non-fragment frontend Active + Excution Core Active//Fragment queueActive = fragemnt jobslot active + fragment frontend Active + ExcutionCore Active + fragment backend active//Non-fragment Active = Non-fragment frontend Active + Excution Core Active//fragment Active = fragment frontend Active + ExcutionCore Active + fragment backend active

GPU_measure.png

注意 GPU 的中断分为 MMU 中断和 Job 中断,上图中 JobManager
Non_fragment slotfragment slot 执行完成和 Non-fragment,fragment 执行完成都会产生中断

ExcutionCore

GPU 最开始被发明出来就是用于图形加速的。在光栅化的渲染框架下,对顶点做变换以及对 Fragment 着色是一种高度独立的任务,两个顶点或者像素之间谁都不需要关心对方的属性,并且它们之间的行为也几乎完全一致,比如说对一个三角形进行平移,则对它的每一个顶点加上相同的向量,区别只有输入:三个顶点的位置数据不同,如果对指令有一定了解的话,会发现这和 SIMD(Single Instruction stream, Multiple Data stream)好像一模一样 事实上,GPUShaderCore就是 SIMD 处理器

Excution Core 的内部结构:
ExcutionCore.png
现在我们重点关注 SIMD 指令和操作数
SIMD 的特点就是,使用一条指令,完成多组数据的同一个运算。用一条伪指令来举例:ADD x, x, y 代表x = x+y。当ExcutioEngine中每一个线程对应的xy寄存器(在 Front-end 中分配)都可以访问的时候,GPU中的程序计数器取出ADD指令,并在每一个线程上执行,只不过对于不同的线程xy的内容不同

Warp Manager

WarpManager从指令缓存中取出指令,并在数据准备完成的时候,提交给 Excution engine执行,指令缓存就是之前说的,Job Manager分解 CPU 传来的Draw Call 后放入的那两个队列

ExcutioEngine

ExcutioEngineSIMD 指令的执行单元,每个 ExcutioEngine 包含1个程序计数器(以下简称PC),8/16个线程,每个线程可以使用 32 个bit寄存器

Load Store unit

负责所有非纹理采样的内存访问,包括数组,结构体,bufferimage等的读写(uniform buffer和编译器可以确定下标的小型数组访问,会被尽可能的优化为寄存器访问),以及寄存器溢出时,读写保存和加载溢出的寄存器。LS unit拥有自己的L1 CacheCompute shader 中使用的 Shared memory 就来自这一部分

这里 image 的读写,是指 imageLoad/Store这样的访问函数,和 imageTexture 这种类型的采样函数严格区分,读取图像的时候,使用 texture unitImageTexture 会更快。

Varying Unit

用于计算插值的固定功能单元

Texture unit

针对纹理采样优化的硬件,双线性采样具有很好的性能功耗。TU 拥有自己的 L1 Cache,并且有专门为Texture优化的机制:优先缓存空间上邻近的像素,而不是地址上邻近的像素

Fragment Back-end

Back-end 用于 Fragment Shading完成后的操作,包括late z test、blend、把像素写到 Tile Memory,当Tile Memory触发写回条件时,把它写回到 DDR里。如果Tile内容和上一帧一样就抛弃,降低写出带宽。当所有的Tile都处理完毕,一个完整的 Framebuffer就绘制完成了,可以用于显示

Memory-port

Memory.png

CPU向 GPU 上传和更新数据,访问纹理,访问超大数组,buffer或者texture回读,访问 SSBO 等都需要用到 MemoryPort 的读写

相关文章:

  • RAG工程-基于LangChain 实现 Advanced RAG(预检索-查询优化)(上)
  • 类和对象(拷贝构造和运算符重载)下
  • 脑机接口技术:开启人类与机器的全新交互时代
  • jupyter notebook汉化教程
  • 【RocketMQ 生产者消费者】- 同步、异步、单向发送消费消息
  • SIEMENS PLC程序代码 赋值 + 判断
  • 操作系统(1)多线程
  • CMake管理外部依赖的模块
  • 极大电视 0.0.5.2| 基于Web的电视直播应用,提供高清、流畅的央视频道和各大卫视直播,完全免费无广告
  • C# 方法的结构与执行详解
  • GD32F407单片机开发入门(二十五)HC-SR04超声波模块测距实战含源码
  • [计算机科学#7]:CPU的三阶段,取指令、解码、执行
  • 2025五一杯数学建模B题:矿山数据处理问题,详细问题分析,思路模型
  • 实习入职的总结
  • RPG_5.角色动画
  • 如何拿奖蓝桥杯
  • UN R79 关于车辆转向装置形式认证的统一规定(正文部分2)
  • 数字智慧方案6157丨智慧医疗建设方案(85页PPT)(文末有下载方式)
  • 结构模式识别理论与方法
  • 内存 “舞台” 上,进程如何 “翩翩起舞”?(转)
  • 本周看啥|《乘风》迎来师姐们,《天赐》王蓉搭Ella
  • 全红婵/陈芋汐夺得跳水世界杯总决赛女子双人10米台冠军
  • 证监会:坚决拥护党中央对王建军进行纪律审查和监察调查的决定
  • 滨江集团:一季度营收225.07亿元,净利润9.75亿元
  • 白玉兰奖征片综述丨国产剧集创作的此消彼长
  • 上海国际咖啡文化节开幕,北外滩集结了超350个展位