英文书 影印版 网站开发,服饰视频网站建设,微网站设计与开发竞赛,北京做推广的公司本文整理一些日常积累的可以优化的方向
一.延迟vector计算
在进行float与vector计算的时候#xff0c;可以先确定float再计算#xff0c;不要多个float一起计算 如#xff1a; highp float f0,f1;highp vec4 v0,v1;v0 (v1 * f0) * f1;优化为 highp float f0,f1;highp vec…本文整理一些日常积累的可以优化的方向
一.延迟vector计算
在进行float与vector计算的时候可以先确定float再计算不要多个float一起计算 如 highp float f0,f1;highp vec4 v0,v1;v0 (v1 * f0) * f1;优化为 highp float f0,f1;highp vec4 v0,v1;V0 v1 * (f0 * f1)二.避免分支语句if和个别for语句
以OpenGL通常处理的图像来说OpenGL的shader在运算的时候会产生成千上万个线程来对不同的点位区域进行计算每个线程都使用同一份shader代码、但是处理的数据不同。为了大幅度提高计算速度OpenGL利用了GPU而GPU的基本调度单位叫做wavefront不同平台理念相同、叫法不同NVIDIA平台叫warpAMD平台叫wavefront等 下面统称为wavefront。wavefront是一组线程的组合既然称之为调度的基本单位自然是GPU会同时处理属于同一个wavefront的所有线程因为他们的计算指令shader从第一行到最后一行是完全相同的只是数据不同而已。GPU正是这样通过single instruction multiple threadSIMT的方式来进行提速的。这有点类似于CPU中的SIMD加速只不过CPU中一次SIMD操作只针对一组数据、需要人为编码控制而GPU的SIMT是从始至终的用相同指令计算所有的线程数据。这样并行度极高从而大幅提升了性能。
但是一旦引入if/for产生分支wavefront结构就被完全破坏掉了会产生diverged wavefront。例如原本4个线程组成一个wavefront一直同步计算突然遇到if语句3个线程if判断为true进入A分支另一个线程if判断为false进入B分支此时这4个线程接下来的指令不再相同原来的这个线程组wavefront就无法同步计算、被迫分开即为diverged wavefront。这时候GPU只能分开执行这两个新产生的wavefront。由于GPU计算资源也是一定的新产生的两个wavefront可能需要排队等待来顺序执行原来是并行执行尤其是wavefront大批量diverged的时候然后新分割出来的wavefront如果要移动到其他GPU计算单元上还需要进行数据复制转移也是很耗时的行为。这些都严重破坏了并行度从而导致性能下降。因此建议最好少使用产生分支的if语句for语句有时候也会产生分支也需要注意。
优化策略 用step方法或者其他的方法替换掉分支语句 step是阶跃函数输入两个参数edgex。如果edge x返回0否则返回1. vec3 a;
if (b 1)
{a 1;
}
else
{a 0.5;
}替换为 vec3 a;
float temp step(b, 1.0);
a 1.0 - temp * 0.5;如果不可避免进行分支操作要先选择可以被优化的分支 编译器有时可以对分支进行一定的优化。If判断条件一般包含三种数据 1静态分支If判断语句仅仅包含常数 2uniform数据分支If判断语句仅仅包含常数或uniform参数 3动态分支其他情况If判断语句中有动态变化的数据。 按道理来说静态数据和uniform数据不会变化编译器应该可以判断并进行编译优化但是对于Android开发来说硬件千差万别目前据我了解对于OpenGL ES 2.0基本上大都只能优化静态分支对于OpenGL ES 3.0通常可以优化uniform数据分支部分机型可能可以优化动态分支。 所以写分支的时候注意分支的类型并且如果升级到OpenGL ES 3.0就基本可以使用uniform数据分支而没有明显的性能损失了。 同理如果for循环的此时是一个整数、即常量那么也不会产生分支只有当for循环的次数也是随着点位的不同动态变化的时候才会产生分支。 相同区块情况可以使用分支 一般来说相邻的点位区域的线程会组合在同一个wavefront中如果一个分支与位置相关例如图像上半部分都是黑色下半部分是彩色而If判断条件是颜色是否为黑色那么大部分情况下同一个wavefront的线程都会在if判断后走同一个分支这样wavefront就不会diverge。或者判断条件是和位置有关的那么大概率也不会diverge。只要不产生diverge就不会对性能有很大影响。 全量代码但保证某些分支不起作用 比如如下 if (a 0) {result funcA();
} else {result funcB();
}可以替换为: result funcA();
result funcB();计算全部的函数这样就避免了分支 很多情况下全量执行所有分支的代码比使用If判断还要快这个可以通过实际测试比较来进行选择。
三. 计算尽量提前到顶点着色器
比如在计算一些面的法向量的时候可以在Vertex Shader中计算完成然后传递给 Fragment Shader减少计算量。
四.使用更少的颜色分量参与计算
五.降低数据的精度
比如从Vertex Shader传递到Fragment Shader的纹理坐标精度从highp改成mediump也会降低一些消耗。
参考
https://blog.csdn.net/qq_30070433/article/details/87392605 https://cloud.tencent.com/developer/beta/article/1370101 https://blog.csdn.net/ShareUs/article/details/94922200