EarlyZ渲染管线优化

EarlyZ相关概念及实际Shader优化

Posted by Luffy on May 30, 2017

前言

最近在整理项目中过往使用的Shader,有一些Shader是从插件如:ShadowGun等移植过来;一些是根据项目新写的,有一些注意事项和风格并不统一。在对Shader的优化整理过程中,主要参考相关的UWA博客和Unity的相关优化文档。

Alpha Testing的使用

Alpha Test通过判断像素的Alpha值来确定是否渲染该像素。AlphaTest示例。 AlphaTest可用于渲染凹面带透明物体(如树木等)。

使用方式:AlphaTest Greater 0.6,当像素值大于0.6时渲染。常用的像素比较指令:

指令 用途
Greater Alpha大于某一值时渲染
GEqual Alpha大于等于某一值时渲染
Less Alpha小于某一值时渲染

而当我在查看Unity Shader 优化文档时发现: 不推荐在IOS等平台上使用,使用时会照成性能浪费。这又是为何?使用AlphaTest直接舍弃掉该像素不尽兴渲染,那又为何会造成浪费呢?

AlphaTest通常使用clip()来实现。在CG手册中,clip()等同于以下代码:当x值小于0时,将其舍弃。

void clip(float4 x)
{
if (any(x < 0))
discard;
}

AlphaTest 与 EarlyZ

根据Wiki中对Early Fragment Test的解释,是一种GPU通过提前进行片元测试,从而越过Fragment Shader阶段的一种优化手段。

如下图所示为正常的RenderPipeline流程:

renderingPipeline

而Unity进行了EarlyZ相关优化后的渲染流程图如下:

renderingPipeline

可以看出,Culling Depth Test位置提前,由原本在Fragment Shader之后变为之前。

那么使用AlphaTest对这个流程有什么影响呢?

原因就在于,若使用AlphaTest即discard,则只有在运行相应的Fragment Shader时才能够判断到底是否渲染改像素,所以,GPU在遇到使用discard关键字的fragment shader时,会关闭EarlyZ,从而造成性能的损耗。

小结

总结了相关Early Depth Test相关知识。 对于IOS平台的Shader编译,在Xcode Debug时发现(有一个Shader编译不过),项目相关Shader被编译(可选)为Metal ,对IOS的Metal Shader相关的知识学习和优化,也已被提上日程 XD