Steam for Linux > 一般討論 > 主題細節
SiPlus 2013 年 06 月 10 日 @ 下午 11 時 06 分
[PULL REQUEST] Optimized Big Picture shaders for Linux (long)
Recently, I found the Big Picture mode shaders code in the Steam folder.

To my surprise, one of them had dynamic conditional branching, which is considered a huge performance dropper, because it doesn't let the GPU use single instruction for all pixels currently processed in parallel.

So I decided to optimize the shaders.

On GitHub, the issue is located there[github.com], and the repo with the updated code is there[github.com].

So, let me explain the biggest changes in the shaders.

Particle shader
The particle shader (tex2dparticle.frag) is that shader with branching I was talking about.

From what I see, the branch condition depends on a varying variable, so it can be different in a single batch of pixels.

Here is the original main() code:

vec4 texcol = color;

vec2 uv = tex.st - 0.5;

float radius = sqrt( dot( uv, uv ) );

float flSharpRadius = ( clamp( particleSharpness, 0.0, 0.98 ) ) / 2.0;
float alpha = 1.0;
if ( radius < flSharpRadius )
{
alpha = 1.0;
}
else
{
alpha = clamp( (1.0 - ( (radius - flSharpRadius) / (0.5 - flSharpRadius ) ) ), 0.0, 1.0 );
}

gl_FragColor.r = color.r * color.a * alpha;
gl_FragColor.g = color.g * color.a * alpha;
gl_FragColor.b = color.b * color.a * alpha;
gl_FragColor.a = color.a * alpha;

So I replaced the branch with mix/step (much faster - even though some instructions are wasted, all pixels in the batch are processed with the same instruction), and the length of main() is now 4 statement lines, while the unoptimized code is 13 SLOC long.

There's nothing wrong if flSharpRadius become 0.5, division by zero is completely fine in shaders and only results in undefined number (or infinity), but you aren't going to use it to color your pixels, because mix will make it 0.0.

The resulting code is:
vec2 uv = tex.st - 0.5;
float radius = sqrt( dot( uv, uv ) );
float flSharpRadius = clamp( particleSharpness, 0.0, 0.98 ) * 0.5;
gl_FragColor = color * vec4( color.aaa, 1.0 ) *
mix( 1.0, clamp( 1.0 - ( radius - flSharpRadius ) / ( 0.5 - flSharpRadius ), 0.0, 1.0 ), step( flSharpRadius, radius ) );

I also replaced division by multiplication (less work for the compiler) and vectorized color/alpha multiplication.

YUV shader
The issue with the YUV color space texture shader is underusing fast vector operations. Vector operations take mainly one instruction (and mostly one cycle, including dot product), and GPUs are designed for vector processing.

The original main() is:
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 version with vector operations:

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 );
}

For the compiler, it would be hard to find out that dot product can be used here, especially in the case of red and blue components. And you can't rely on compiler optimizations in GLSL, because every graphics card vendor has shader different compiler, unlike HLSL, which is compiled solely by fxc.exe.

Three 0.5 subtractions are also replaced by one. The 0.42723 constant is there to allow subtracting 0.5 from the red component, and is calculated with (0.5 - 1.1643 * 0.0625) formula.

The same code is also merged with the YUV part of fancyquaduber.frag shader.

Other shaders
In other shaders, the optimizations are mostly small, like replacing .r=;.g=;.b=;.a=; with vec4 assignment and using 1-argument vector constructors.

As I said before, fancyquaduber.frag includes my YUV optimization, so it's probably the biggest optimization of other shaders.
最後修改者:SiPlus; 2013 年 06 月 11 日 @ 上午 1 時 07 分
顯示 1-15,共 25 則回應
< >
LOLCAT 2013 年 06 月 11 日 @ 上午 12 時 34 分 
I don't think Valve would just take code from a user and incorporate it into Steam, because
- It makes their own employee, who wrote the original bad
- They'd have to employ you
- They'd have to pay you
- They'd have to give credit to you

They'll either not react at all (as usual) or come up with a tale about how their code is better.
SiPlus 2013 年 06 月 11 日 @ 上午 12 時 59 分 
I'm contributing this completely for free, I don't need any credit (maybe in update history, but I don't care).
Shark 2013 年 06 月 11 日 @ 上午 1 時 31 分 
Nice, how big is the difference?
Oerthling 2013 年 06 月 11 日 @ 上午 3 時 04 分 
LOLCAT 發表:
I don't think Valve would just take code from a user and incorporate it into Steam, because
- It makes their own employee, who wrote the original bad

Perhaps. (and for the sake of argument I'm just assuming here that there is no obscure reason why the original code might make sense after all).

But programmers get corrected all the time. Code is often knowingly written in a suboptimal way - for example because time constraints didn't allow for better solutions.
The original programmer might have this already on his/her list of stuff to fix.

Known suboptimal code is not always fixed right away - if the cost of testing and possible interaction with other code is considered too high at the time for the payoff.

In any way - not fixing known bugs makes you look much worse than writing the original buggy software.

LOLCAT 發表:
- They'd have to employ you

They don't have to do that.

LOLCAT 發表:
- They'd have to pay you

1. They don't *have* to do that.
2. Why would that bother them?

LOLCAT 發表:
- They'd have to give credit to you

So?
Non-problem.

LOLCAT 發表:
They'll either not react at all (as usual) or come up with a tale about how their code is better.

Possible. But not necessarily so.
None of your reasons make much sense anyway.

1. They might not notice or ignore this.
2. They might notice and then fix it quietly without using the provided code (it might have already been on a list of things to fix after all).
3. They might accept the offered free code and write a short thank you note.

Option #3 would only get them positive feedback. No downside actually.

There's whole operating systems written by people who fix each others code all the time. Total non-problem for experienced programmers.
最後修改者:Oerthling; 2013 年 06 月 11 日 @ 上午 3 時 05 分
SUSEd 2013 年 06 月 11 日 @ 上午 3 時 52 分 
Can i change those files myself?
LOLCAT 2013 年 06 月 11 日 @ 上午 4 時 58 分 
JUSTME 發表:
snip
We are talking about a company here, not a person. Even if they didn't employ him and pay him, they'd have to make a contract and stuff like that. (Every company is terrified of lawyers and lawsuits, especially in the US.) Take the person to their office, meet him, talk to him, let him sign the paper etc. This costs more than just ignoring him, especially that the original code works as well.
6wl 2013 年 06 月 11 日 @ 上午 5 時 13 分 
No they don't - SiPlus just needs to put his code under free to use license even for commercial software. (possibly MIT, can't remember off the top of my head).
SiPlus 2013 年 06 月 11 日 @ 上午 5 時 24 分 
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

Okay now?
SUSEd 2013 年 06 月 11 日 @ 上午 5 時 34 分 
You should use WTFPL licence.
Shark 2013 年 06 月 11 日 @ 上午 5 時 58 分 
Lol, this is WTFPL:

DO WHAT THE ♥♥♥♥ YOU WANT TO PUBLIC LICENSE
Version 2, December 2004

Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>

Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.

DO WHAT THE ♥♥♥♥ YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

0. You just DO WHAT THE ♥♥♥♥ YOU WANT TO.
Tribaal 2013 年 06 月 11 日 @ 下午 12 時 39 分 
Nice! Thanks a lot for your time :)
Oerthling 2013 年 06 月 11 日 @ 下午 1 時 25 分 
LOLCAT 發表:
JUSTME 發表:
snip
We are talking about a company here, not a person. Even if they didn't employ him and pay him, they'd have to make a contract and stuff like that. (Every company is terrified of lawyers and lawsuits, especially in the US.) Take the person to their office, meet him, talk to him, let him sign the paper etc. This costs more than just ignoring him, especially that the original code works as well.

0 of your claims are true.

Doesn't matter if it is a company or person. They don't have to do any of those things - but still could use the offered code - if they want to.
And even if they want to pay it would be very easy to use a boilerplate contract and pay a handful of freelance contractor hours and mail the paperwork. There's no need to meet anybody in any office. You're making this all up out of thin air.

Again, there's a ton of source being shared and bought every day. And that includes companies using said code.

Companies use Linux often together with some proprietary software package of their own running with it. Somehow they survived that a lot of people provided source for that.

You really think Linus goes through a lot of paperwork about every single patch he accepts into the Kernel? Meets every single contributor?
Or the LibreOffice project.
Or Mozilla?

As long as the author/copyright owner agrees with the usage there is no problem for anybody (or the creator could simply release it to the public domain - i.e. relinquish any copyright claims).

Valve might well ignore/not notice this - or have good technical reasons to go another way. No idea. But if they notice and want to use it – they easily could. There'd be no problem.
Tea 2013 年 06 月 11 日 @ 下午 4 時 27 分 
LOLCAT 發表:
I don't think Valve would just take code from a user and incorporate it into Steam, because
- It makes their own employee, who wrote the original bad
- They'd have to employ you
- They'd have to pay you
- They'd have to give credit to you

They'll either not react at all (as usual) or come up with a tale about how their code is better.

https://github.com/ValveSoftware/Source-1-Games/issues/718#issuecomment-18160474
Kamikaze 2013 年 06 月 11 日 @ 下午 4 時 44 分 
SiPlus - perhaps file this and your licence on valve's github so they're more likely to notice it. You could possibly even look at e-mailing someone at valvesoftware too.
Kamikaze 2013 年 06 月 11 日 @ 下午 4 時 45 分 
@Tea - wow that's awesome to see them accept community contributions :)
顯示 1-15,共 25 則回應
< >
每頁: 15 30 50
張貼日期: 2013 年 06 月 10 日 @ 下午 11 時 06 分
回覆: 25