添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Shader中的if分支优化tips

Shader中的if分支优化tips

背景:

很多开发者现如今知道编写shader时都应该避免使用if来避免性能问题。通常的做法是 会采用诸如step(), 或者lerp()去做一个hack。但是这样并没有解释所谓的分支判断造成的性能问题究竟在哪里。本文简要谈谈编写shader过程中需要使用if分支时可能会遇到的问题和原因,以及相应的注意点和tips。

不同种类的分支

分支判断条件

首先决定shader中分支判断的种类的因素是分支判断的条件。如果分支判断的数据是constant的(比如说一个shader properties指定的常量),那么这个if判断不会造成性能问题。因为对于GPU来说,所有的在同一个warp中的线程都在读取同一个数据,这使得GPU中的compute units在读取数据进行处理时能够直接非常快速地读取constant buffer,从而能够充分地利用SIMD的并行性去高效处理pixel或vertex(这里可以看我之前写的一篇compute shader的文章)。而不会造成因为需要分支判断而产生需要对一个warp处理两遍的情况。

if(_ConstantValue > 0.5)
   do something here
}
Apple GPU中的constant buffer之于fragment processing

而如果分支判断的数据是动态数据,比如说对于一个texture的采样结果,那么对于每个正在被处理的像素都需要去走一遍这个分支判断。对于这种情况编译器有两种选择。第一种是GPU fast comparison(unity中可以使用UNITY_FLATTEN开启),如果分支判断的执行语句如果足够的简单的话,编译器会选择对if的两个分支同时进行处理,最后再选择一个正确的结果。第二种是 真分支判断,也是通常需要避免的情况(unity中可以使用UNITY_BRANCH开启)。就以texture为例的情况来说,需要避免使用非常多高频信息的texture来做分支判断条件。因为当一个warp中处理的pixel需要不同的分支进行处理,会使得GPU对于pixel的一些优化手段失效(比如group 2x2 pixel大的quad进行绘制)。

2x2大小的pixel组成一个quad


分支执行的内容

另一点关于shader分支需要注意的是每个分支执行的内容是什么。如果对texture进行自动的mipmap level sample而没有指定确切的level的话,很有可能造成error。

fixed4 color = fixed4(0,0,0,0);
UNITY_BRANCH
if (screenPos.x > 0.5) 
  float2 uv = screenPos * 2.0;