[转] Shader 优化相关资料整理

优化必须先搞清楚什么是渲染管线


注:
应用程序阶段:主要是CPU与内存打交道,例如碰撞检测,计算好的数据(顶点坐标、法向量、纹理坐标、纹理)就会通过数据总线传给图形硬件 。
几何阶段:其实上图有个问题(网上不少博客也没写清楚这个问题),根据 OpenGL 蓝宝书(Super Bible)上的讲解,“几何图元装配”应该位于“细分着色器”阶段之后(细分着色器处理的还是一个个 Patch),然后再进入“几何着色器”(因为几何着色器处理的基础就是一整个图元)生成新的图元,在该阶段的最后,就是我们熟悉的MVP变换视锥体裁剪操作了。


光栅化阶段:进入光栅化器进行光栅化(还包括剪刀测试、深度测试、模板测试),最后输出到屏幕的 framebuffer 中。

编写shader时的一些建议
转自:http://www.cnblogs.com/sifenkesi/p/4716791.html

1、只计算需要计算的东西
尽量减少无用的顶点数据, 比如贴图坐标, 如果有Object使用2组有的使用1组, 那么不 要将他们放在一个vertex buffer中, 这样可以减少传输的数据量;
避免过多的顶点计算,比如过多的光源, 过于复杂的光照计算(复杂的光照模型);
避免 VS 指令数量太多或者分支过多, 尽量减少 VS 的长度和复杂程度;

2、尽量在 VS 总计算
通常,需要渲染的像素比顶点数多,而顶点数又比物体数多很多。所以如果可以,尽量将运算从 FS 移到 VS,或直接通过 script 来设置某些固定值;

3、指令优化【Unity】
在使用Surface Shader时,可以通过一些指令让shader优化很多。
  通常情况下,Surface shader的很多默认选项都是开启的,以适应大多数情况,但是很多时候,你可以关闭其中的一些选项,从而让你的shader运行的更快:  
(1) approxview 对于使用了 view direction 的shader,该选项会让 view dir 的 normalize 操作 per-vertex 进行,而不是 per-pixel。这个优化通常效果明显。   (2) halfasview 可以让Specular shader变得快一些,使用一个介于光照方向和观察方向之间的 half vector 来代替真正的观察方向 viewDir 来计算光照函数。
 (3) noforwardadd Forward Rende r时,完全只支持一盏方向光的 per-pixel 渲染,其余的光照全部按照 per-vertex 或 SH 渲染。这样可以确保shader在一个pass里渲染完成。 
 (4) noambient 禁掉 ambient lighting 和 SH lighting,可以让 shader 快一点儿。

4、浮点数精度相关:
 float:最高精度,通常32位 
 half:中等精度,通常16位,-60000到60000, 
 fixed:最低精度,通常11位,-2.0到2.0,1/256的精度。 
 尽量使用低精度。对于 color 和 unit length vectors,使用fixed,其他情况,根据取值范围尽量使用 half,实在不够则使用 float 。  在移动平台,关键是在 FS 中尽可能多的使用低精度数据。另外,对于多数移动GPU,在低精度和高精度之间转换是非常耗的,在fixed上做swizzle操作也是很费事的。

5、Alpha Test
  Alpha test 和 clip() 函数,在不同平台有不同的性能开销。  通常使用它来剔除那些完全透明的像素。  但是,在 iOS 和一些 **Android **上使用的 PowerVR GPUs上面,alpha test非常的昂贵。6、Color Mask
  在移动设备上,Color Mask 也是非常昂贵的,所以尽量别使用它,除非真的是需要。

shader中用for,if等条件语句为什么会使得帧率降低很多?

作者:空明流转链接:https://www.zhihu.com/question/27084107/answer/39281771来源:知乎著作权归作者所有,转载请联系作者获得授权。

  1. For和If不一定意味着动态分支
    在GPU上的分支语句(for,if-else,while),可以分为三类。Branch的Condition仅依赖编译期常数此时编译器可以直接摊平分支,或者展开(unloop)。对于For来说,会有个权衡,如果For的次数特别多,或者body内的代码特别长,可能就不展开了,因为会指令装载也是有限或者有耗费的额外成本可以忽略不计Branch的Condition仅依赖编译期常数和Uniform变量一个运行期固定的跳转语句,可预测同一个Warp内所有micro thread均执行相同分支额外成本很低Branch 的 Condition 是动态的表达式这才是真正的“动态分支”会存在一个Warp的 Micro Thread 之间各自需要走不同分支的问题2. 跳转本身的成本非常低
    随着IP/EP(Instruction Pointer/Execution Pointer)的引入,现代GPU在执行指令上的行为,和CPU没什么两样。跳转仅仅是重新设置一个寄存器。3.Micro Thread 走不同分支时的处理
    GPU本身的执行速度快,是因为它一条指令可以处理多个 Micro Thread 的数据(SIMD)。但是这需要多个 Micro Thread 同一时刻的指令是相同的。如果不同,现代GPU通常的处理方法是,按照每个Micro Thread的不同需求多次执行分支。[cpp] view plain copy
x = tex.Load();  
if(x == 5)  
{  
    // Thread 1 & 2 使用这个路径  
   out.Color = float4(1, 1, 1, 1);   
}  
else  
{  
    // Thread 3 & 4 使用这个路径  
   out.Color = float4(0, 0, 0, 0);  
} 

比如在上例中,两个分支的语句Shader Unit都会执行,只是不同的是如果在执行if分支,那么计算结果将不会写入到thread 3 和 4的存储中(无副作用)。这样做就相当于运算量增加了不少,这是动态分支的主要成本。但是如果所有的线程,都走的是同一分支,那么另外一个分支就不用走了。这个时候Shader Unit也不会去傻逼一样的执行另外一个根本不需要执行的分支。此时性能的损失也不多。并且,在实际的Shader中,除非特殊情况,大部分Warp内的线程,即便在动态分支的情况下,也多半走的是同一分支。4. 动态分支和代码优化难度有相关性
这一点经常被忽视,就是有动态分支的代码,因为没准你要读写点什么,前后还可能有依赖,往往也难以被优化。比如说你非要闹这样的语句出来:[cpp] view plain copy

if(x == 1)  
{  
   color = tex1.Load(coord);  
}  
else if(x == 2)  
{  
   color = tex2.Load(coord);  
}  

你说编译器怎么给你优化。说句题外话,为啥要有TextureArray呢?也是为了这个场合。TextureArray除了纹理不一样,无论格式、大小、坐标、LoD、偏移,都可以是相同的。这样甚至可以预见不同Texture Surface上取数据的内存延迟也是非常接近的。这样有很多的操作都可以合并成SIMD,就比多个Texture分别来取快得多了。这就是一个通过增加了约束(纹理格式、大小、寻址坐标)把SISD优化成SIMD的例子。

定位渲染通道瓶颈的方法
转自:http://blog.csdn.net/rabbit729/article/details/6398343

一般来说, 定位渲染通道瓶颈的方法就是改变渲染通道每个步骤的工作量, 如果吞吐量也改变了, 那个步骤就是瓶颈.。找到了瓶颈就要想办法消除瓶颈, 可以减少该步骤的工作量, 增加其他步骤的工作量。  一般在光栅化之前的瓶颈称作”transform bound”, 三角形设置处理后的瓶颈称作”fill bound”
定位瓶颈的办法:

  1. 改变帧缓冲或者渲染目标(Render Target)的颜色深度(16 到 32 位), 如果帧速改变了, 那么瓶颈应该在帧缓冲(RenderTarget)的填充率上。
  2. 否则试试改变贴图大小和贴图过滤设置, 如果帧速变了,那么瓶颈应该是在贴图这里。
  3. 否则改变分辨率.如果帧速改变了, 那么改变一下pixel shader的指令数量, 如果帧速变了, 那么瓶颈应该就是pixel shader. 否则瓶颈就在光栅化过程中。
  4. 否则, 改变顶点格式的大小, 如果帧速改变了, 那么瓶颈应该在显卡带宽上。
  5. 如果以上都不是, 那么瓶颈就在CPU这一边。

转自:http://blog.csdn.net/panda1234lee/article/details/54861041

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,013评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,205评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,370评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,168评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,153评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,954评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,271评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,916评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,382评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,877评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,989评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,624评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,209评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,199评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,418评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,401评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,700评论 2 345

推荐阅读更多精彩内容