原文出处:GPU渲染管线和硬件架构浅谈

序言

一、GPU渲染管线

1.1 渲染管线简述

所谓渲染管线,就是CPU传送给GPU一堆数据(顶点、纹理等),经过一系列处理,最后渲染得出来一副二维图像。有以下几个阶段。

1.1.1 应用程序阶段

1.1.2 顶点处理阶段

1.1.3 光栅化阶段

1.1.4 逐片元操作

1.2 IMR: Immediate Mode Rendering

上图展示了一个非常经典的IMR渲染管线,也是桌面端最常见的GPU架构。GPU会在每个drawcall提交中,按照管线的顺序处理每个图元。

1.2.1 优势:

1.2.2 劣势:

1.3 TBR: Tile-based Rendering

1.3.1 为什么要使用TBR架构

1.3.2 TBR架构的原理

1.3.3 优势

1.3.4 劣势

1.4 TBDR: Tile-Based Deferred Rendering

1.5 总结

二、GPU硬件架构

2.1 GPU和CPU的差异

这张图展示了CPU和GPU的硬件差异。

CPU和GPU的差异可以描述在下面表格中:

  
CPUGPU
延迟容忍度
并行目标任务(Task)数据(Data)
核心架构多线程核心SIMT核心
线程数量级别1010000
吞吐量
缓存需求量
线程独立性

2.2 CPU的缓存体系和指令执行过程

虽然本文主要讲的是GPU架构,不过CPU和GPU有很多地方是相通的,同时又有一些设计方向是相反的。了解CPU可以帮助我们更好的理解GPU的执行过程。

2.2.1 内存的硬件类型

2.2.2 CPU的缓存体系

2.2.3 CPU指令的执行过程

2.3 GPU渲染过程

具体渲染过程,其实就是经典的渲染管线的执行过程。可以跟上一部分的渲染管线流程图对照阅读。推荐阅读 Life of a triangle - NVIDIA's logical pipeline 一文。

2.4 桌面端GPU硬件架构

上图展示的是NVIDIA Fermi架构的示意图。不同的GPU,架构差异较大,但是大体都包含下列核心组件:

2.5 Shader Core的主要构成单元

2.6 GPU的内存结构

2.6.1 UMA (Unified Memory Architeture)

2.6.2 GPU缓存的分类
GPU缓存结构

内存访问速度

内存的存取速度从寄存器到系统内存依次变慢:

      
存储类型RegisterShared MemoryL1 CacheL2 CacheTexture/Const MemorySystem Memory
访问周期11~321~3232~64400~600400~600
NVIDIA的内存分类

查资料的时候经常会看到这些概念,但是NVIDIA的内存分类是为CUDA开发服务的,与游戏开发或者移动GPU还是有一些差异的。所以这里只需要简单了解即可。

2.6.3 Cache line
2.6.4 Memory Bank和Bank Conflict

2.7 GPU的运算系统

2.7.1 SIMD (Single Instruction Multiple Data) 和 SIMT (Single Instruction Multiple Thread)

2.7.2 Warp 线程束
2.7.3 Stall 和 Latency Hiding (延迟隐藏)

2.7.4 Warp Divergence

2.8 其他重要概念

2.8.1 Pixel quad

2.8.2 EarlyZS
2.8.3 Hierarchical-z和Tile-based Rasteration

这两个是硬件提供的优化。

2.8.4 Register Spilling和Active Warp

2.8.5 Mipmap

2.8.6 纹理采样和纹理过滤

2.9 从硬件角度理解GPU的执行逻辑

2.9.1 GPU中的可编程元件和固定管线元件
2.9.2 从硬件角度看EarlyZ
2.9.3 GPU核心的乱序执行和保序

三、移动平台GPU架构

3.1 PowerVR架构

3.1.1 PowerVR GPU管线

3.1.2 PowerVR GPU硬件架构

3.2 Mali架构

3.2.1 Mali GPU管线

3.2.2 Mali GPU四代架构演变

Mali GPU的架构演变非常直观的展示了移动GPU的进化过程。再加上Mali的开发资料比较多,所以这里分别介绍了Mali的四代架构。这里可以和上文介绍的G PU管线和硬件架构的理论形成参考和对照。

Utgard (2007)

Midgard (2012)

Bifrost (2016)

Valhall (2019)

3.2.3 Mali GPU其他技术

Forward Pixel Kill
IDVS: Index-Driven Vertex Shading

AFBC: Arm Frame Buffer Compression

AFBC是一种无损的压缩协议和格式。可以最小化SoC的不同IP块(硬件单元)之间的数据传输数量。使用AFBC可以有效节省带宽,降低功耗。这个对开发者是无感知 的。其他平台也都有类似的压缩技术。

Transaction Elimination

Transaction Elimination也是一种很有效的降低带宽的方法。在有些情况下,只有部分Tile中的内容会变化(例如摄像机不动,一个Tile中只有静态物体)。此时通过比较该Tile前一次和本次的渲染结果的CRC值,可得到Tile是否变化,如果不变,那么就没有必要执行Tile到System Memory的写回操作了,有效地降低了带宽占用。

Hierarchical Tiling

根据图元的大小选择合适的Hierarchy Level的Tile。降低Tiling阶段对主存的读取和写入开销。

Shared Memory

3.3 Adreno架构

Flexable Render
Low Resolution Z

3.4 总结

四、常见问题的分析与讨论

4.1 DrawCall对性能的影响

4.2 AlphaTest和AlphaBlend对性能的影响

4.2.1 桌面平台

4.2.2 移动平台

Alpha tested primitives will do the following:
ISP HSR: Depth and and stencil tests (no writes)
Shading: Colours are calculated for fragments that pass the tests
Visibility feedback to ISP: After the shader has executed, the GPU knows which fragments were discarded and which where kept. Visibility information is fed back to the ISP so depth and stencil writes can be performed for the fragments that passed the alpha test
When discard is used, pixel visibility isn’t known until the corresponding fragment shader executes. Because of this, depth and stencil writes must be deferred until pixel visibility is known. This reduces performance as the pixel visibility information has to be fed back to the ISP unit after shader execution to determine which depth/stencil positions need to be written to. The cost of this can vary, but in the worse case the entire fragment processing pipeline will stall until the deferred depth/stencil writes complete.

4.3 不透明物体是否需要排序

bool hasAdrenoHSR = caps->gles.isAdrenoGpu && !isAdreno2 && !isAdreno3 && !isAdreno4;
caps->hasHiddenSurfaceRemovalGPU = caps->gles.isPvrGpu || hasAdrenoHSR;

4.4 PreZ pass/Depth prepass是否有必要

4.5 Shader中的分支对性能的影响

4.5.1 分支对性能的影响

4.5.2 编译器对shader的优化

4.5.3 分支的性能隐患

4.5.4 multi_compile的副作用

如果不使用if-else,那么另外一个选择就是multi_compile。遗憾的是,使用multi_compile同样会有明显的副作用。

4.5.5 关于分支的建议

4.6 Load/Store Action和Memoryless

4.6.1 Load/Store Action

4.6.2 Memoryless

4.6.3 Render Target切换

4.6.4 避免CPU回读GPU数据

4.6.5 Pixel local storage

4.6.6 移动平台延迟渲染优化

4.7 MSAA对性能的影响

4.7.1 MSAA

下面的表格显示了Mali Bifrost GPU,bits/pixel和Tile大小的关系。

   
Family16x16 Tile16x8 Tile8x8 Tile
<= Bifrost Gen 1128 bpp256 bpp512 bpp
>= Bifrost Gen 2256 bpp512 bpp1024 bpp

4.7.2 Alpha to coverage

4.8 Shader的优化建议

结语

参考资料

PowerVR (Imagination / Apple)

Mali (Arm)

Adreno (Qualcomm)

GPU硬件架构及渲染管线

开源库

KM的文章

内部课程