通常,需要渲染的像素比顶点数多,而顶点数又比物体数多很多。所以如果可以,尽量将运算从 FS 移到 VS,或直接通过 script 来设置某些固定值;
在使用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 快一点儿。在移动设备上,Color Mask 也是非常昂贵的,所以尽量别使用它,除非真的是需要。
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. 动态分支和代码优化难度有相关性
这一点经常被忽视,就是有动态分支的代码,因为没准你要读写点什么,前后还可能有依赖,往往也难以被优化。比如说你非要闹这样的语句出来: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这一边。
新闻热点
疑难解答