Jump to content
  • Advertisement
Sign in to follow this  
megatron242

Varying variables cause massive framedrops

This topic is 3076 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, I'm trying to implement a lighting shader to add "lamps" in the scene, and I'm having this problem, where it appears that every varying variable I use, to pass data from the vertex shader, to the fragment shader, reduces the framerate in ~15 FPS. When I'm putting 3 "lamps", it means passing 3 floats, and 3 vec3 varying variables, which reduces my FPS for almost an half. I'm using a Lenovo T400, Windows7, with ATI Mobility Radeon HD 3400 Series, driver version 8.641.1.1000 (the latest version). Any help would be appreciated, Vince

Share this post


Link to post
Share on other sites
Advertisement
Performance drop in FPS is meaningless, better measure performance as time to render (in milliseconds). Only then you will know the real performance impact of using varyings.

And also, how many varyings are you using in total? Can you post your shader source?

Share this post


Link to post
Share on other sites
Passing varying should not cause a slowdown. You are probably doing a lot of calculations in your fs.

Share this post


Link to post
Share on other sites
Well, here are both the VS and FS (I've stripped them to the bare minimum):


Vertex shader:

<source>
varying vec4 ambientGlobal;
varying vec3 normal;

varying vec3 lightDir0, lightDir1, lightDir2;
varying float dist0, dist1, dist2;

void main()
{
vec4 ecPos;
vec3 aux;

normal = normalize(gl_NormalMatrix * gl_Normal);

ecPos = gl_ModelViewMatrix * gl_Vertex;

// Light0
aux = vec3(gl_LightSource[0].position-ecPos);
lightDir0 = normalize(aux);
dist0 = length(aux);

// Light1
aux = vec3(gl_LightSource[1].position-ecPos);
lightDir1 = normalize(aux);
dist1 = length(aux);

// Light2
aux = vec3(gl_LightSource[2].position-ecPos);
lightDir2 = normalize(aux);
dist2 = length(aux);

ambientGlobal = gl_LightModel.ambient * gl_FrontMaterial.ambient;

gl_TexCoord[0] = gl_MultiTexCoord0;
gl_TexCoord[1] = gl_MultiTexCoord1;

gl_Position = ftransform();
}
</source>



Fragment shader:

<source>
varying vec4 ambientGlobal;
varying vec3 normal;

varying vec3 lightDir0, lightDir1, lightDir2;
varying float dist0, dist1, dist2;

uniform sampler2D tex;
uniform sampler2D texLm;

uniform vec4 lightCol0, lightCol1, lightCol2;

uniform int addGlow, hasLightMap;
uniform vec4 glowColor;

void main()
{
vec3 n;
float NdotL;
vec4 color = ambientGlobal;
vec4 color2;

n = normalize(normal);

// Light0
NdotL = max(dot(n,normalize(lightDir0)),0.1);
color += NdotL / (dist0*lightCol0);

// Light1
NdotL = max(dot(n,normalize(lightDir1)),0.1);
color += NdotL / (dist1*lightCol1);

// Light2
NdotL = max(dot(n,normalize(lightDir2)),0.1);
color += NdotL / (dist2*lightCol2);

gl_FragColor = texture2D(tex,gl_TexCoord[0].st)*color;

if (hasLightMap == 1 && addGlow == 1)
{
if (texture2D(texLm,gl_TexCoord[0].st) != vec4(0,0,0,0))
gl_FragColor += glowColor;
}
}
</source>

Share this post


Link to post
Share on other sites
Perhaps you can pack the varyings together

varying vec3 lightDir0, lightDir1, lightDir2;
varying float dist0, dist1, dist2;

becomes
varying vec4 lightDir0_dist0;

and you use
lightDir0_dist0.xyz and lightDir0_dist0.w

it might not improve performance. I would not know what else to suggest because your fs is simple and should not be a problem for your modern GPU. My shaders have perhaps 5 times the instruction count as yours.

Share this post


Link to post
Share on other sites
This might be a dumb question as I've never used OpenGL before, but are you actually doing the calculations on the GPU? Maybe you're using a reference rasterizer, which would be using the CPU and not the GPU. Make sure your GPU supports the shaders you're using.

Share this post


Link to post
Share on other sites
@freeworld - OpenGL2 is supported by the device, so I don't have any reason to think it's done in CPU.

On any rate, I'm starting to think that it's a driver issue. The reason, is that once in a while, the _same_ code runs twice as fast (and smooth). I wonder if anyone ever experienced this kind of behavior ? The specs of the machine I'm using is in the original post.

Share this post


Link to post
Share on other sites
Hm I also do not see any reason for the slowdown.
If it is due to expensive equations you should try
to minimize calls to normalize and other square-root-using
functions.
For example you pass normal=normalize(...) and in the fragmentshader
normalize(normal) which is unnecessary.
If it really is a problem with passing varyings why not pass the lamp data
as uniform?

Share this post


Link to post
Share on other sites
Maybe it is the if statements in the fragment shader? I know it is not an efficient operation on GPU, especially when you are doing per-pixel tests. I think all pixels in a thread group execute the same conditional branch initially, and you might get some bad perf if some pixels are branching one way and some are branching another way. Really want to minimize conditionals whenever possible.

Try just commenting out both if statements and see if your perf goes up.

Also:

ecPos = gl_ModelViewMatrix * gl_Vertex;
...
gl_Position = ftransform();




You might want to throw out ftransform() here in favor of
gl_Position = gl_ProjectionMatrix * ecpos;

You're already computing the eye space coordinate of the vertex, theres no reason to force gpu to calculate it a second time through ftransform(), which is depreciated anyway.

Share this post


Link to post
Share on other sites
I am wondering about this pice:

-------------------------------------------------------
gl_FragColor = texture2D(tex,gl_TexCoord[0].st)*color;

if (hasLightMap == 1 && addGlow == 1)
{
if (texture2D(texLm,gl_TexCoord[0].st) != vec4(0,0,0,0))
gl_FragColor += glowColor;
}
-------------------------------------------------------

If it goes through the if statements it does..

gl_FragColor += glowColor;

Thus is reads from gl_FragColor before adding and writing to it again?
Is this allowed I thought you were only allowed to write to it.

I would do this:

------------------------------------------------------
color2 = texture2D(tex,gl_TexCoord[0].st)*color;

if (hasLightMap == 1 && addGlow == 1)
{
if (texture2D(texLm,gl_TexCoord[0].st) != vec4(0,0,0,0))
color2+=glowColor;
}
gl_FragColor = color2;
-------------------------------------------------------

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!