06-rasterization-and-setup

第 6 篇:三角形设置与光栅化(Triangle Rasterization and Setup)

原文:Part 6

一句话定位

现代硬件光栅化通常把三角形转成可增量计算的边函数,再分层遍历 tile/像素块,产出覆盖掩码;它不在同一个“大循环”里顺便完成着色和纹理采样。

边函数

对每条有向边可建立形如 E(x, y) = A·x + B·y + C 的线性函数。采样点位于三角形内外,可由三个边函数的符号判断。因为从一个像素移动到相邻像素只需给 E 加固定增量,这种表示非常适合并行硬件和定点实现。

三角形设置阶段预先计算:

  • 各边方程及增量;
  • 包围盒、面积和面朝向;
  • 用于属性/深度插值的平面参数;
  • 与填充规则、采样位置相关的偏置。

设置成本几乎按三角形计,而不是按覆盖像素计。这解释了为什么大量亚像素三角形会让前端/设置单元成为瓶颈。

粗到细的分块遍历

flowchart TD T[屏幕空间三角形] --> B[计算包围盒与边方程] B --> C[Coarse Raster<br/>测试较大 tile] C -->|完全在外| X[丢弃 tile] C -->|相交/在内| F[Fine Raster<br/>测试小块/采样点] F --> M[coverage mask]

大块测试能一次拒绝许多像素,细阶段再生成精确覆盖。层次遍历兼顾大三角形吞吐与局部数据组织,也方便与 hierarchical Z、ROP 分区和内存 tile 对齐。

填充规则与水密性

两个三角形共享一条边时,采样点不能被双方都排除形成裂缝,也不应被双方重复覆盖。Top-left 一类规则通过对“恰好落在边上”的样本做确定性归属,保证拼接图元的一致覆盖。

实现常用定点或严格受控的舍入,原因不是 GPU 不会浮点,而是覆盖判定必须在所有相关单元中可复现。几何中的 T-junction 则没有真正共享同一条边,有限精度下更容易产生裂缝,应在模型/细分阶段修复。

小三角形与细长三角形

  • 小三角形可能只贡献 0~1 个像素,却仍支付完整的装配、设置和至少一次 tile 测试成本。
  • 细长三角形可能跨过大量 tile,但每个 tile 只覆盖极少像素,粗阶段效率很差。
  • 优化不能只看总三角形数,还要看屏幕空间大小、形状、分布,以及每个 primitive 产生的有效像素数。

术语对照

英文 中文理解 作用
triangle setup 三角形设置 预计算边/插值方程等常量
edge function 边函数 判定采样点相对边的位置
coarse rasterization 粗光栅化 以 tile 为粒度筛选
fine rasterization 细光栅化 生成像素/样本覆盖掩码
coverage mask 覆盖掩码 指明哪些 sample 被图元覆盖
top-left rule 左上填充规则 处理恰落在共享边上的样本
sliver triangle 细长三角形 跨 tile 多、有效覆盖低

面向 UMD/KMD 的阅读提示

  • UMD 配置 polygon mode、cull、front face、sample count、sample locations、conservative raster 等状态。
  • 某些“看似 shader 的输出”会影响固定功能设置,例如 clip/cull distance、layer、viewport index。
  • 调优时结合 primitive、clipped primitive、rasterized tile、PS invocation 等 counter,判断瓶颈在设置、粗光栅还是像素端。
  • 这部分几乎都在硬件数据面;KMD 的职责主要是保证命令和资源可执行,不参与逐三角形判断。

自测与实验

  • 保持总屏幕覆盖面积近似相同,把网格不断细分,观察何时从像素瓶颈转为前端瓶颈。
  • 为什么用包围盒逐像素测试虽正确,却不一定有高吞吐?
  • MSAA 增加的是 coverage sample,为什么不一定按相同比例增加 pixel shader invocation?

本篇总结

光栅化硬件的核心是“把几何转成规则、局部、可批量判断的覆盖问题”;边函数和分块层次是实现这一点的关键。

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