1. GPU并行数据架构
- Shader的调用按线程进行,线程被划分为warps,每个warp容纳32个线程
- 单指令多数据流(SIMD)
- 当一个线程需要到内存抓取数据时,挂起该线程并进行下一个线程,当一个warp全部挂起时,切换到下一个warp
- 如果Shader需要的寄存器过多,能同时存在的线程和warp就会变少,从而有可能不能掩盖从内存读取数据的延迟
- 当Shader中存在 if 和循环等动态分支语句时,会影响效率
2. GPU管线概览
可编程阶段
- 顶点着色器,曲面细分(可选),几何着色器(可选),像素着色器
可配置阶段
- 屏幕映射——需要配置窗口和视口大小、比例等
- 混合阶段——各种buffer、多种模式可以配置
固定功能阶段
- 裁剪,光栅化
3. 可编程着色器
- 多种着色器使用相同指令集架构,然后每个着色器有独自的特定功能
- 使用通用着色核心来合理分配各种着色器的执行
- 每个可编程着色阶段有两种输入:常量和变量。常量在一个drawcall中对所有执行单元都相同,不同drawcall之间则会更新;变量在一个drawcall中每个执行单元都有可能不同;纹理是一个特殊的常量
- 在一个drawcall中常量只需要存储一次,而变量需要对每个顶点或像素都存储一次,因此能够使用的常量寄存器比变量的寄存器多得多
- 静态分支以常量作为流控制,因此在一个drawcall中不会产生线程分歧;动态分支受变量控制,因此不同顶点或像素会执行不同代码,相应地会影响性能
4. 顶点着色器
- 操作顶点数据,通常都应该含有将模型空间坐标转换到齐次裁剪空间的操作
- 不能创建新的顶点或者销毁已有顶点
- 不同顶点之间数据不互通,相互独立,从而可以并行计算
- 顶点着色器通常用来做形变效果
5. 曲面细分着色器
- hull shader, tessellator,domain shader
- hull shader决定要生成的三角形数量,并且可以操作输入曲面的控制点(从而变换原曲面形态),然后向tessellator发送细分参数和细分类型,向domain shader发送细分参数和控制点数据
- tessellator是固定功能,生成新的顶点
- domain shader处理所有数据,生成新的三角形
6. 几何着色器
- 改变物体拓扑结构
- 移动设备不推荐使用
- 几何着色器的输出可以流出管线,然后重新进入管线以实现各种效果如粒子效果
- 输出顺序与输入顺序相同
7. 像素着色器
- 可以选择两种不同的插值方式
- 可以改变深度值,计算雾效,透明检测
- 多渲染目标(MRT)和延迟渲染
- 同一个pass中,像素着色相互独立,但是pass之间可以传递数据
- 像素着色器可以获得梯度值,间接得知相邻像素信息(光栅化以2×2的方式进行),限制是不能有动态分支
8. 计算着色器
- 将线程组成线程组,在一个线程组中共享一块内存实现数据暂存,避免与CPU通信,从而提高效率
- 在管线中的位置没有明确限制