Jump to content
  • Advertisement
Sign in to follow this  
d0Sm4o20

Bizarre GLSL link error

This topic is 2566 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 guys, this is driving my crazy. I have 1 vertex shader and 1 fragment shader linked into 1 program (so far, so good :)

However, on the linking stage, my shader crashes, *but only if I make a very specific code alteration*. Here's what *works*:

fragment:


#version 410

in vec3 vnormal;
in vec3 vlight[10];

out vec4 color;
uniform vec4 fill_color;

void main(void) {
color = fill_color;
}



vertex:


#version 410

layout(location = 0) in vec4 position;
layout(location = 1) in vec3 normal;

layout(std140) uniform matrices_block {
mat4 projection;
mat4 modelview;
mat3 normal;
} mat;

out vec3 vnormal;
out vec3 vlight[10];

uniform int num_lights;

void main(void) {
vnormal = mat.normal * normal;
vec4 vertex_eye = mat.modelview * position;

int j = 0;
for (int i=0; i<num_lights; i++) {
j = 0;
vlight[j] = vec3(0.0);
}

gl_Position = mat.projection * mat.modelview * position;
}



This works fine. Compiles, runs, etc. I know it looks a little crazy that I'm using "j" to index vlight, and setting j=0 every time in the loop, but hear me out for a second. Here's what doesn't work in the vertex shader:

If i move this:


j = 0;
vlight[j] = vec3(0.0);



To this:


vlight[j] = vec3(0.0);
j = 0;



The shader programs refuse to link. What's worse is, there's no output log from glGetShaderInfoLog, so I can't tell what's going wrong. This is really weird behavior, and it's starting to make me question my drivers. If it's any help, my graphics card is an Nvidia GeForce GTX 485M with driver 280.13.

Anyone have any insight on what I can poke at next? Thanks!

Share this post


Link to post
Share on other sites
Advertisement
Update:

I've managed to narrow it down to the uniform "num_lights". From my client code, I'm setting num_lights to 1. However, if I comment out "uniform int num_lights" and add an "int num_lights = 1;" to my main(), the code works again.

So there's some weirdness with setting the uniform, which is creating even more weirdness in the code. I'm using glProgramUniform1i, and the uniform location is non-negative (it's 34), and the value is an integer. So there doesn't seem to be any error with that.

Any insight? Thanks

Share this post


Link to post
Share on other sites
Try getting rid of the useless line "j=0" and just use vlight[0] instead for the time being. Sometimes compilers optimize things. You already said that line changed things. Or just do vlight anyway since that is what your loop seems to need anyway.

Share this post


Link to post
Share on other sites
What may be going on is that I have had (and others) where shaders do not work if you dont explicitly use a uniform. Sometimes shaders unroll your loops and since your loop never uses the index "i", it again is probably optimizing it. So STOP IT!

Share this post


Link to post
Share on other sites

What may be going on is that I have had (and others) where shaders do not work if you dont explicitly use a uniform. Sometimes shaders unroll your loops and since your loop never uses the index "i", it again is probably optimizing it. So STOP IT!


I probably should've clarified why I wasn't using "i" to index vlight. I was using "i" first, which is where the error first surfaced. So instead, I created "j" just to see if I could get the same bad behavior with a variable that wasn't being compared to num_lights, which it did.

I'll keep poking at it more. I'm clearly messing around with some very undefined behavior, so this is turning out to not be easy.

Share this post


Link to post
Share on other sites
What I mean is that your loop regardless of what variable you use, is technically at the core it is not a loop, so the compiler might be smart enough to fiddle with your code. So whoever rated me down should understand that and help people out instead of just browsing and rating people down. So many losers on here. As I said, even things like sending uniforms I have had several Nvidia cards that return a -1 index on uniforms variables that I only declare and never use. So it could be something like this. Obviously everything looks pretty much fine, just that your loop is the only suspicious piece of code. So make that loop actually do something and see what happens. If it fixes it then don't waste 3 hours debugging code that isn't really "correct".

int j = 0;
for (int i=0; i<num_lights; i++)
{
j = 0;
vlight[j] = vec3(0.0);
}

might just compile to:
int j = 0;
vlight[j] = vec3(0.0)
hence no num_lights variable anymore.

Sometimes compilers will go further and se that j is not really a variable either and it might just go to:
vlight[0] = vec3(0.0)

Share this post


Link to post
Share on other sites
Yeah, I think I see what you're saying about unrolling the loops. I googled "glsl uniform loop" and it seems that there have been a lot of people with issues of using a uniform in the expression part of a loop. This could be my problem. If I set the expression to a constant value, either through a #define, or with some fixed value in the code, it works fine.

I double-checked my glGetUniformLocation and it's not returning -1, so I think that's fine. It must be the uniform in the loop creating undefined behavior. Might be a bug in the driver. I'm going to upgrade my driver right now actually and see if that solves it.

Share this post


Link to post
Share on other sites
After a lot of poking at the shader code (and updating my drivers), I've come to the conclusion that I can't do the following things together:

I can't have a loop based on a uniform expression AND have that loop alter an "out" array.

For example, this works:



#version 420

layout(location = 0) in vec4 position;
out int derp[10];

uniform int num_lights;

void main(void) {
for (int i=0; i<10; i++) {
derp = i;
}

gl_Position = position;
}



And this works:

#version 420

layout(location = 0) in vec4 position;
out int derp[10];

uniform int num_lights;

void main(void) {
int j = 0;
for (int i=0; i<num_lights; i++) {
j += i;
}

gl_Position = position;
}


But this doesn't:


#version 420

layout(location = 0) in vec4 position;
out int derp[10];

uniform int num_lights;

void main(void) {
for (int i=0; i<num_lights; i++) {
derp = i;
}

gl_Position = position;
}





Really bizarre behavior.

Share this post


Link to post
Share on other sites

So the last one just doesnt link still? Or does it give you an invalid uniform location?


Well, it never actually gets to the point where I get the uniform location. The code fails on linking the compiled shaders, so I can't even assign a uniform yet.

That's a weird limitation if I can only use a uniform for loops that don't modify an "out" variable, but I'll have to accept it I guess if it's true.

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.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!