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

xan*_*ndy 2 performance android frame-rate fragment-shader opengl-es-2.0

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

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;
}
Run Code Online (Sandbox Code Playgroud)

代码工作正常,但有趣的是,即使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;
}
Run Code Online (Sandbox Code Playgroud)

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

顺便说一下,我正在使用GLES20在Android 2.2中编写以上内容.

有没有专家知道着色器有什么问题?

小智 6

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


Pet*_*ter 6

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

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