虚幻从5.4以后提供了完整的VRS Tier2支持,并且在Nanite的场景下额外提供了对Nanite特定优化的Software Variable Shading Rate的支持。 具体可以见这篇博客的介绍 Nanite-enabled Variable Rate Shading in Unreal Engine 5.4
在Nanite场景下,Software的模式会更适合Nanite的渲染模式。
Variable Rate Shading Tier1 / Tier2?
Variable-rate shading (VRS) - Win32 apps | Microsoft Learn
微软的文章可能是对VRS的来龙去脉,支持特性讲的最清楚的,由于这个特性是由硬件支持的,所以DX12的API也可以无缝迁移到其他API上。
另外一个可以参考的资料是VK_KHR_fragment_shading_rate
的提案
Vulkan-Docs/proposals/VK_KHR_fragment_shading_rate.adoc at main · KhronosGroup/Vulkan-Docs
Tier1 / Tier2的主要区别:
Tier1: 兼容性好,只支持Per-Draw设置 Tier2:更灵活,支持在屏幕空间设置和通过VertexShader / Geometry Shader输出一个值来控制Shading Rate,兼容性一般
硬件兼容性问题
硬件Vendor | Tier1 | Tier2 |
---|---|---|
AMD | 只支持到2x2 | OK |
Nvidia | 支持到4x4 | OK |
Intel | ? | ?(没硬件来测试) |
Mali1 | From Mali G715(约2022年), max 4x4 | from Mali G715 |
Adreno2 | From Adreno 660(约2021年) | maybe 8Gen1? |
Apple | A13(2019) | A13(2019) |
PC / Console都没啥问题,Intel虽然没测试但是应该也是支持的很好的。 只需要注意AMD不支持2x2以上的VRS,Nvidia可以支持到4x4。
Mobile上Apple是跟进的最早的,很早就实现了Tier1 / Tier2的VRS支持。 高通最早是在888支持Tier1的VRS,从硬件上来看好像实现VRS Tier2也没啥阻碍。 只是一开始驱动没就位,很多888的手机都不支持VRS Tier2(vulkan报告VK_KHR_fragment_shading_rate这个扩展不存在)。 我找了一个8Gen1的手机测试就支持Tier2了。
mali支持VRS功能更晚一些,基本要到2022年的旗舰芯片才开始支持VRS,不过好在第一批支持的时候就已经Tier1 / Tier2就位了。
从2025年来看,现在新发的芯片,无论是移动端/Console对VRS的支持都没啥问题了。
UE VRS的配置方案
PC当然毫不犹豫的使用 Tier1 + Tier2结合的方式即可。 如果不想做过多的改造,那么直接打开虚幻的VRS Tier2功能就可,虚幻提供了一个FContrastAdaptiveImageGenerator
的算法来处理Tier2 Shading Rate Image
的生成。
Mobile这里要斟酌一下了。因为基于上一帧的数据来计算Shading Rate Image,相当于要过一次Compute Shader的全屏后处理,这个开销不便宜。会极大的抵消VRS带来的性能提升。 Mobile这里还是要把Tier1的VRS用好,尽量依靠LOD系统来选择不同的Shading Rate。
借用一张高通的博客的图来看一下,远处的山脉都切换成了很低的Shading Rate
引擎改造: Per Material Instance Shading Rate
虚幻对VRS Tier1感觉没啥兴趣,连最基本的在MaterialInstance上覆盖Shading Rate的功能都没有提供。
这里可以参考Intel的文档提供的Unreal改造方案, Variable Rate Shading Tier 1 Usage Guide
在材质面板上支持覆盖这个MI的Instance的Shading Rate。
然后根据Mesh的不同LOD选择不同的Material Instance,以支持不同LOD使用不同Shading Rate的功能。
引擎改造: Tier1 VRS Debug View
同理,虚幻也缺少一个Tier1 VRS的Debug View来查看当前的场景内的Shading Rate的功能。
虚幻的VRS DebugView功能只提供了Tier2的Shading Rate Image
的可视化功能,Tier1的啥也看不到。
有人给虚幻提过PR,但是被无情拒绝了,可能epic的大哥们觉得VRS Tier1老掉牙了没啥好看的吧。
Mobile没人权也不是一天两天了。
[UE5 Feature] DX12 shading rates viewmode by mamoniem · Pull Request #8113 · EpicGames/UnrealEngine
可以参考这个PR合并一下。
VRS的特殊情景下的处理
PixelShader Modify Depth:
Nvidia: 可以用
NV的文档里提了这种情况, 注意最后一行
Advanced API Performance: Variable Rate Shading | NVIDIA Technical Blog
Do not modify the output depth value from the pixel shader. If the pixel shader modifies depth, VRS is automatically disabled.
AMD: VRS Tier2 不能用
在AMD显卡上测试得时候发现了问题,材质连了PixelDepthOffSet
后,开着VRS Tier2的话会出现奇怪的像素pattern,用renderdoc抓帧发现会出现有部分像素ZDepth Test不过。用VRS Tier1没有问题,恐怕还是个驱动问题..
最后只有在启用了PixelDepthOffset的材质上禁用VRS Tier2来解决兼容性问题(通过设置VRS Combinar可以只选择来自管线的Shading Rate,忽略来自Image的Shading Rate,需要改点引擎代码)。
Pixel Shader With Clip
这个虚幻的注释里留了一点线索。 如果VRS着色的像素clip了,会直接丢弃一个block的像素,造成肉眼可见的闪烁
bool FMaterialResource::IsVariableRateShadingAllowed() const {
return Material->bAllowVariableRateShading
&& !IsMasked() // When using pixel discard, coarse shading causes the whole block to get discarded resulting in noticeable artifacts
&& !Material->HasCustomPrimitiveData() // When using custom primitive data, Nanite can't determine which primitive ID to use for shading clusters
&& !Substrate::IsSubstrateEnabled(); // For now disable VRS when Substrate is enabled due to incorrect data replication between neighbor pixels
}
虚幻默认检查到一个材质是Masked的时候,会直接无视VRS的设置。
Pixel Shader Writes UAV
这个是项目里有个特性用到了这个功能,试验了一下,和VRS不太兼容。被复制的周围的像素不会写UAV。 会造成后续Shader读UAV的数据的时候读到没被初始化的值造成逻辑上的问题 没啥好的解决方案,只能禁用了