为什么以下将拖动Fragment Shader(Open GL ES 2.0)的性能

时间:2011-05-04 05:35:10

标签: android performance opengl-es-2.0 frame-rate fragment-shader

我在片段着色器中有以下代码:

precision lowp float;

varying vec2 v_texCoord;
uniform sampler2D s_texture;

uniform bool color_tint;
uniform float color_tint_amount;
uniform vec4 color_tint_color;

void main(){
    float gradDistance;
    vec4 texColor, gradColor;
    texColor = texture2D(s_texture, v_texCoord);
    if (color_tint){
        gradColor = color_tint_color;
        gradColor.a = texColor.a;
        texColor = gradColor * color_tint_amount + texColor * (1.0 - color_tint_amount);
    }
    gl_FragColor = texColor;
}

代码工作正常,但有趣的是,即使我传入的所有color_tint都是假的,上面的代码仍然会导致严重的性能拖累。比较时:

void main(){
    float gradDistance;
    vec4 texColor, gradColor;
    texColor = texture2D(s_texture, v_texCoord);
    if (false){
        gradColor = color_tint_color;
        gradColor.a = texColor.a;
        texColor = gradColor * color_tint_amount + texColor * (1.0 - color_tint_amount);
    }
    gl_FragColor = texColor;
}

后者可以达到40+ fps,而第一个可以达到18 fps。我仔细检查过,第一个传递的所有color_tint都是假的,所以块永远不会被执行。

BTW,我正在使用GLES20在Android 2.2中编写上述内容。

任何专家都能知道着色器有什么问题吗?

2 个答案:

答案 0 :(得分:6)

片段着色器上的分支非常慢,如果可能的话,避免它们。使用color_tint_amount为0表示无色调。预乘color_tint_color并保存每个像素的乘法。 make color_tint_amount = 1.0 - color_tint_amount。 (所以现在1.0意味着没有gradColor)这些着色器每秒运行数百万次,你必须保存每个周期。

答案 1 :(得分:6)

我不是片段着色器的专家,但我认为第二个会更快,因为整个if语句可以在编译时删除,因为它永远不会是真的。在第一个中,它不能告诉color_tint在运行时始终为false,因此每次都需要检查并分支。分支可能很昂贵,特别是在通常用于可预测的串行编程的图形硬件上。

我建议你尝试将其重写为无分支 - 达伦的回答在这方面有一些很好的建议。