03-pipeline-and-vertex-processing

第 3 篇:3D 流水线总览与顶点处理(Pipeline Overview, Vertex Processing)

原文:Part 3

一句话定位

顶点阶段把索引与顶点数据组织成可并行批次,在通用 shader 执行单元上运行,然后按后续图元装配需要保存和排序结果。

API 阶段与硬件数据流

API 常把流水线画成 IA → VS → PA → Rasterizer → PS → OM。硬件实现更像多个生产者/消费者队列:固定功能单元准备工作,通用执行单元处理 batch,结果进入缓冲,再交给下一固定功能阶段。阶段边界未必对应独立物理模块。

flowchart LR I[Index Buffer] --> IA[Input Assembler] V[Vertex Buffers] --> IA IA --> C[索引/顶点复用与批次构建] C --> S[Shader Core 上运行 VS] S --> O[结果缓冲与顺序整理] O --> PA[Primitive Assembly]

输入装配与顶点复用

  • 索引绘制允许多个图元共享顶点。若一个顶点已经着色且结果仍在缓存中,就不必再次运行 VS。
  • 缓存大小有限,驱动/应用提供的索引顺序会影响命中率。网格重排优化的目标之一就是让共享顶点在时间上靠近。
  • 硬件通常成批收集“需要新计算的顶点”,同时保留索引到结果位置的映射。批次边界要照顾完整图元,避免后续装配阶段拿不到一整个三角形。
  • 非索引绘制省去索引查找,但不能自动获得跨图元复用。

为什么要批处理

单个顶点的 shader invocation 太小,无法高效调度到宽 SIMD/SIMT 机器上。派发器会聚合一组顶点,再把它们作为 wave/warp 类执行批次运行。批处理摊销调度成本,也提供足够的并行工作来隐藏指令与内存延迟。

分支会让同一执行批次中的 lane 走不同路径。硬件常以掩码分段执行各路径,因此控制流分歧会降低有效利用率。这里的关键不是“GPU 不能分支”,而是同一批次越一致越高效。

结果为何还要缓冲

VS 完成顺序可能不同:缓存未命中、分支、纹理访问和资源争用都会引入变化。后续 PA 需要按照正确的图元关系消费顶点,因此需要保存结果并恢复所需顺序。GPU 不是让所有阶段锁步前进,而是在局部使用 FIFO、标签和完成跟踪解耦阶段。

术语对照

缩写/英文 中文 作用
IA 输入装配器 解释顶点布局、索引并取数据
VS 顶点着色器 对每个输入顶点产生输出属性
PA 图元装配 按拓扑把顶点组合成点/线/三角形/patch
post-transform cache 变换后缓存 复用已着色顶点结果
lane 执行通道 一个 SIMD/SIMT 批次中的元素
divergence 分歧 lane 控制流不一致导致分段执行

面向 UMD/KMD 的阅读提示

  • 这篇主要对应 UMD 的 pipeline/state 编译与硬件前端配置,KMD 通常只看见资源和命令,不理解“这是哪个三角形”。
  • 追踪 vertex buffer 描述符:基址、stride、format、offset、越界/鲁棒访问语义在哪里落实?
  • 追踪 shader key:哪些 API 状态会产生不同 VS 变体,哪些由固定功能寄存器表达?
  • 查 draw packet 如何表达 indexed/non-indexed、base vertex、instance count 与 primitive topology。

自测与实验

  • 用同一网格比较顺序索引与随机索引,观察 VS invocation 数或 GPU counter。
  • 为什么“VS 输出必须最终按图元关系可重建”不要求每个 batch 的完成时间严格有序?
  • instance divisor 应在输入装配的哪个位置影响地址计算?

本篇总结

顶点处理是“索引驱动的数据获取 + 复用 + 宽执行 + 有序交接”,其中缓存与批次组织往往和 ALU 本身同样重要。

posted @ 2026-10-26 21:57  Sailxiv  阅读(3)  评论(0)    收藏  举报