白泽图

  • 文章
    • Unity渲染
    • Unity项目开发
    • 工具
    • 数学
    • 算法
    • 网站搭建
    • 网络&操作系统
蒋程个人博客
互联网技术经验总结&分享
  1. 首页
  2. Unity渲染
  3. 正文

UnityShader if判断优化

2020-12-28 3199点热度 0人点赞 0条评论

参考:Unity Shader: 优化GPU代码--用step()代替if else等条件语句

原文核心思路:

对于GPU来讲,各个顶点各个像素都在进行大量的并行运算,每个片段着色器都在同步运行,只有所有像素全部完成计算,才会进行下一次运算, 在片段着色器中,每个片段处理器每条指令操作上百个像素,如果有些片段(像素)采取一个分支而有些片段不采用另一个分支,则所有片段都会执行两个分支,但只在每个片段应该采取的分支上写入寄存器。不论何种策略,对追求高并行度的GPU来讲,分支是必须要同步的,那么最慢的case就会造成短板效应。另外,if/endif等流程控制操作对GPU来讲有较高的指令开销(4个时钟周期,Geforce6) 因此在GPU编程中,if else ,switch case和嵌套if语句等等是不推荐的会影响GPU的工作效率。相应的,可以用step()等函数进行替换,用阶梯函数的思维来构建条件语句。这样,所有的线程都执行完全一样的代码,加大了并行化计算的可能性,消除条件分支指令的性能损耗

归纳:

1.GPU高度并行,使用if逻辑判断,效率取决于最慢的分支情况

2.if语句需要用掉四个时钟周期(这个太费,特别在逐像素时)

3.通过数学函数将判断结果控制在0和1上,再通过与0和1的运算,实现if语句的效果

应用(部分代码说明):

if(passedTime<=maxTotalTime)
{
   o.vertex = UnityObjectToClipPos((v.vertex + vertexOffset) + float4(v.tangent.zw, 0, 0) * scale)
}
else
{
   o.vertex = fixed4(-2,0,0,1);
}

上面的代码在顶点着色器中处理顶点动画效果,时间到达后隐藏

修改为:

float isPlaying = step(passedTime, maxTotalTime);
o.vertex = UnityObjectToClipPos(((v.vertex + vertexOffset) + float4(v.tangent.zw, 0, 0) * scale) * isPlaying + fixed4(-2, 0, 0, 1) * (1 - isPlaying));

1、Step(a,x):如果x>=a返回1;如果x<a返回0

2、Clamp(x,a,b):如果x<a返回a;如果x>b返回b;如果在a和b之间就返回x

标签: 暂无
最后更新:2022-08-26

蒋程

这个人很懒,什么都没留下

点赞
< 上一篇
下一篇 >

文章评论

您需要 登录 之后才可以评论

COPYRIGHT © 2023 白泽图. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang

登录
注册|忘记密码?