ValveSoftware/steam-for-linux — pull request #2569 by SiPlus (2013-06-07 15:21:03+00:00)
Title: Vectorized Big Picture YUV shader on Linux and probably Mac

In the YUV shader used by Big Picture on Linux (and, I think, Mac), I replaced scalar operations with vector ones, because vector operations are mostly single instructions and are faster than their unrolled scalar equivalents.

Here is the original code (uniforms, varyings and compiler omitted):

```c
void main (void)
{
vec2 texHalf = tex.st/2;
float y = texture2DRect( Texture0, tex.st ).r;
float u = texture2DRect( Texture1, texHalf ).r;
float v = texture2DRect( Texture2, texHalf ).r;

y = 1.1643*(y-0.0625);
u = u-0.5;
v = v-0.5;

gl_FragColor.r = y+1.5958*v;
gl_FragColor.g = y-0.39173*u-0.81290*v;
gl_FragColor.b = y+2.017*u;
gl_FragColor.a = 1.0;
}
```

And here is the vectorized code:

```c
const vec3 mulRed = vec3( 1.0, 0.0, 1.5958 );
const vec3 mulGreen = vec3( 1.0, -0.39173, -0.8129 );
const vec3 mulBlue = vec3( 1.0, 2.017, 0.0 );

void main (void)
{
vec2 texHalf = tex.st * 0.5;
vec3 yuv = vec3(
1.1643 * texture2DRect( Texture0, tex.st ).r + 0.42723,
texture2DRect( Texture1, texHalf ).r,
texture2DRect( Texture2, texHalf ).r, 1.0 ) - 0.5;
gl_FragColor = vec4( dot( yuv, mulRed ), dot( yuv, mulGreen ), dot( yuv, mulBlue ), 1.0 );
}
```

As you see, I removed multiple passes for `y`, `u` and `v`. `dot` also takes one instruction (and one cycle), so it is used instead of manual multiply-accumulate.

The number `0.42723` is `0.5 - 1.1643 * 0.0625`, precalculated so `- 0.5` can be used on the entire vector.