|
【图形基础】MSAA 最简攻略
讲 AA 的文章有很多,其中经典AA技术当属 MSAA, 但由于涉及到软硬件多个概念,图形新手要把所有扩展了解一圈容易晕,这里对其中涉及到的重要概念及步骤整理一番,减少读者的理解成本。
简单描述下AA (反走样)
这里指的 AA 是 Anti-Aliasing, Aliasing 意为信号失真,表现在数字图形上常表现为边缘锯齿(走样)。而 Anti-Aliasing 就是用来改善表现的反走样技术。
本文主要讨论在游戏中常见的走样:几何走样 。
正常来说,几何采样发生在图形管线的几何光栅化阶段,当离散的屏幕像素用来表达连续的几何边缘的时候,走样就发生了:
这里可以看到,走样的根本原因是采样的频率跟不上原图像的信号频率。
所谓的反走样,一般是提升采样率来改善这种走样。比如可以对像素进一步划分多个 sample 点来进多次采样的结果进行混合,"软化"锯齿。
反走样技术可以大致分为:
1. Spatial Antialiasing (空间反走样)
2. Post Process Antialiasing (后处理反走样)Spatial Antialiasing 指通过超采样的方式(比如我们下面要讲的MSAA) 来反走样,而 Post Process Antialiasing 则是类似于图像处理的方式来反走样。
MSAA
先说下为什么超采样能改善走样,这是因为采样数提升后,最终的像素颜色将由N倍的采样数混合而成,让像素的呈现更接近于真实图像。比如说 Full Scene Antialiasing(FSAA) 是以N倍的渲染代价来实现反走样,这种方式简单粗暴但代价巨大。
而 MSAA 可以看作是 FSAA 的优化版本,通过硬件和管线的配合,让这一部分代价可被接受。它的思路简单总结就一句话:
把重度的 Fragment shading 从 sample frequency 降为 pixel frequency 也就是说着色计算还是逐pixel的,深度/模版逐 sample (sample 数等于总的超采样的采样数),仅把逐pixel的着色结果拷贝给通过深度/模版测试的 sample
再简单点理解就是,同一个三角形覆盖到的 sample 共享一个着色结果 ,写入 sample buffers 中。
效果如下图所示:
由于可以看出,当 sample 都在一个三角内时,像素的着色成本并没有增加,仅在三角形的边缘处发生了多次采样。
这里有个值得注意的是,边缘处的着色次数取决于这些 sample 总共覆盖了多少个三角形
再详细点可以看下参考资料里的 RasterizationRules: 1
接下来继续挖掘 MSAA 里的关键细节。
MSAA 所需的带宽成本?
MSAA 相较于SSAA,所需的存储及带宽并没有减少,比如说 MSAA 4x 所需的带宽成本是两倍。这在 IMR(Immediate-Mode Renderer) 中这些都是实打实的带宽消耗,而 Tile-Base 架构中则可以在硬件层面部分隐藏掉带宽开销(后面细讲)
MSAA 需要硬件哪些支持,整个处理流程大概是怎么样的?
简单分三步:
- 在光栅化阶段进行多重采样 (多出来的采样点生成方式有随机、均匀等), 详见引用2
- 在着色阶段,对像素进行着色,并复制到所覆盖的 sample
- Reslove 把多重采样的结果混合为逐像素的结果
上面所有过程都是 硬件层处理,在开放自定义 Reslove 的硬件上可对 MSAA Buffer 自行实现Reslove。
移动端的 MSAA
现在移动端的 GPU 基本都是 Title-Based Rendering 的架构,Title-Base 的好处是可以减少GPU与主存的交互(带宽), 基于title来,在tile内的读写是 GPU 的 on-chip Memory(片上存储器),在片上存储器上读写可认为是"免费" 的,当然这里得打个引号。
在移动端的各家实现中,会优先在 on-chip Memory 实现多采样及Reslove, 但一般支持到 2 倍 MSAA 可以认为代价比较小。当然这也分不同的厂商。
这里看一下各家GPU厂商是怎么说:
Arm Mali - 引用:3
- Use 4x MSAA because it is not expensive and provides good image quality improvements.
- Use the EXT_multisampled_render_to_texture extension render-to-texture multisampling, this extension can render multisampled data directly into a single-sampled image in memory, without needing a second pass.
- Use more than 4x MSAA without checking performance, as it is not full throughput.
在 19年的 Arm Mali GPUs Best Practices Developer Guide 里还举了例子
大致可以理解为超4倍就会硬解失败。但这里也不要理解为能硬解就没有代价,只是代价相对比较小
Andreno 引用 - 4
- You can do 2x-level MSAA without incurring any significant additional cost in the rendering pipeline, but above that level it can become expensive.
在2倍情况下可以在 GMEM (on-chip)内处理,增加带宽很小,但超过 2 倍就不行。
PowerVR 引用 - 5
- 2x MSAA is virtually free on most PowerVR graphics cores (Rogue onwards), while 4x MSAA+ will noticeably impact performance.
2 倍几乎免费,4倍则对性能有明显的影响
原因也说的很明白
- This is partly due to the increased on-chip memory footprint, which results in a reduction in tile dimensions (for instance 32 x 32 -> 32 x 16 -> 16 x 16 pixels) as the number of samples taken increases
虽然可以在片上内存处理,但随着采样数的增加,变相地减少了每个 title 可容纳的像素数,也就相当于增加了要处理的 title,成本就上来了。
然后说一下,MSAA 本身的限制。
对开 Alpha Testing 的边缘无效
因为 Alpha Testing 的原理就是在着色之前,把低于某个透明值的像素扔掉,发生在像素着色之前,相当于把像素内的所有 sample 都扔掉了,所以该锯齿还是锯齿。
跟延迟管线的兼容性不好
你大概率听说过,在延迟管线中,MSAA 并不适用,那是为啥不适用呢,因为在延迟管线中,几何过程会在存储在几张中间结果的 GBuffer 上,这样让 MSAA 的带宽成倍地增加,也没法好好地利用 TBR 的特性,所以在 延迟上一般会选用 Post Process Antialiasing, 具体我也会开另一篇文章来单独解析。
综上,可知 MSAA 对带宽需求高,有硬件实现依赖,对延迟管线不友好等,但也有意外之喜:
两个被动Buff
- 当在一个三角形屏占比小于一像素时,在 多重采样的情况下也能贡献颜色值
- 可以此基础上应用 Alpha to Coverage(把透明物体当不透明处理,免去了排序、Blend 等消耗), 效果不如直接的 Alpha Blend, 但性价比不错。引用 - [7]
最后知乎上还有个类似关于 MSAA的十万个为什么的问答,有兴趣可以看看
对多重采样(MSAA)原理的一些疑问?
[1]: 光栅化规则 - Win32 apps
[2]: https://en.wikipedia.org/wiki/Multisample_anti-aliasing
[3]: Documentation - Arm Developer
[4]: https://developer.qualcomm.com/software/snapdragon-profiler/app-notes/anti-aliasing-with-adreno
[5]: MSAA Performance
[7]: https://bgolus.medium.com/anti-aliased-alpha-test-the-esoteric-alpha-to-coverage-8b177335ae4f
[8]: fengliancanxue:深入剖析MSAA |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|