0
\$\begingroup\$

I hav a fragment shader like this:

#version 330 core

in vec4 v_color;
in vec2 v_texCoords[10];

out vec4 frag_color;

uniform int actual_textures;
uniform sampler2D u_texture[10];

void main() {
    vec4 final_color = texture(u_texture[0], v_texCoords[0]);
    for(int i = 1; i < actual_textures; i++){
        vec4 tex = texture(u_texture[i], v_texCoords[i]);
        final_color = tex * tex.a + final_color * (1 - tex.a);
    }

    frag_color = v_color * final_color;
}

But somehow this slows my game down by 30 - 40fps in comparison to this approach:

#version 330 core

in vec4 v_color;
in vec2 v_texCoords[10];

out vec4 frag_color;

uniform sampler2D u_texture[10];

void main() {
    vec4 final_color = texture(u_texture[0], v_texCoords[0]);
    vec4 tex = texture(u_texture[1], v_texCoords[1]);
    final_color = tex * tex.a + final_color * (1 - tex.a);
    tex = texture(u_texture[2], v_texCoords[2]);
    final_color = tex * tex.a + final_color * (1 - tex.a);
    //...

    frag_color = v_color * final_color;
}

Why does a single loop slow the gpu down so much?

\$\endgroup\$
  • \$\begingroup\$ Are you sure you're iterating actual_textures times in the non-loop approach? \$\endgroup\$ – clabe45 Aug 15 '17 at 14:25
  • \$\begingroup\$ yes, both times actual_textures is 3 \$\endgroup\$ – mrdlink Aug 15 '17 at 14:31
  • \$\begingroup\$ What graphics card are you using? The GLSL compiler for your driver should be unrolling that loop. \$\endgroup\$ – Honeybunch Aug 15 '17 at 14:51
  • \$\begingroup\$ @Honeybunch would it be able to unroll it when actual_textures is a uniform int variable that could change between draw calls? Adapting to a change in its value would require a recompile to unroll to a different number of iterations, so I think the compiler would be forced to leave the loop loopy. \$\endgroup\$ – DMGregory Aug 15 '17 at 15:06
  • \$\begingroup\$ Oh that's a good point. A good test would be to hard code the range of the loop and see if that gives performance back. \$\endgroup\$ – Honeybunch Aug 15 '17 at 15:10
2
\$\begingroup\$

I've encountered this issue when implementing other shader types with certain hardware configurations.

I believe the issue lies with texture(u_texture[i], v_texCoords[i]); : because the graphics hardware performs prefetch on texture units, it needs to be able to predict to some degree what it will be fetching, or you experience performance drop similar to a cache miss.

Unrolling the loop allows the code to perform the prefetch properly, allowing for a higher framerate.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.