专栏/如何在shader中避免使用if else

如何在shader中避免使用if else

2018年11月06日 14:03--浏览 · --点赞 · --评论
粉丝:1490文章:50

       今天和同事讨论GPU如何实现求导(求偏导),过程中又学习了一下GPU的工作模式。然后发现了我以前的一个误解:我以前以为shader中动态分支会造成性能损失50%,其实这只是一个估计值。实际情况下,GPU性能最坏情况是无分支的1/8 (N卡GTX480以上为1/16),而最好情况也只是无分支的7/8 (N卡GTX480以上为15/16),各种情况取平均值大概是 1/2 。

       首先补充一下GPU中分支语句的种类。GPU中一共有三种分支语句,第一种是 #if #else,由宏来实现,被称作静态分支,在编译期决定,没有性能损失;第二种是if else语句,但是if条件中仅有uniform变量和常量组成,在运行期相当于 #if #else,也没有运行期损失(但是驱动判断static uniform branch有轻微消耗);第三种就是真正的if else语句,也就是动态分支。

       先举一个简单的例子,来说明去除动态分支的方法吧。


可以被优化成:


如果使用HLSL,则应用 step 函数取代GLSL中的 sign 函数

       

对于代码:

则可以优化成:

       通过这两个例子,大概可以看出来目的了。这种优化的实质,就是分支合并,手工计算了所以分支的情况,再只取有用的部分。这种优化只会在分支部分损耗加倍,不会造成老旧GPU那样整个shader性能折半的情况。

       接下来列举一些常用的优化分支函数。

常用关系运算符优化

常用逻辑运算符优化

给浮点数求余数,HLSL应使用 fmod 函数;GLSL应使用 modf 函数,且只有openGL 3.x/openGL ES 3.x 中才能使用


投诉或建议