1

So I'm about to loose my mind.

I'm writing an android app, a native activity to be exact. All is fine except that attributes and uniforms seems to be optimized out in my shader.

Vertex Shader:

#version 100

attribute vec3 position;

void main() {

    gl_Position = vec4(position, 1);

}

Fragment Shader:

#version 100

precision highp float;

uniform vec3 color;

void main() {

    gl_FragColor = vec4(color, 1);

}

Shader Compilation:

unsigned int shader = glCreateProgram();

unsigned int v = glCreateShader(GL_VERTEX_SHADER);
unsigned int f = glCreateShader(GL_FRAGMENT_SHADER);


glShaderSource(v, 1, &vertex, nullptr);
glShaderSource(f, 1, &fragment, nullptr);


glCompileShader(v);
if (check_error(v, GL_COMPILE_STATUS, false)) {
    LOGE("Failed to compile vertex shader");
}

glCompileShader(f);
if (check_error(f, GL_COMPILE_STATUS, false)) {
    LOGE("Failed to compile fragment shader");
}


glAttachShader(shader, v);
glAttachShader(shader, f);

glLinkProgram(shader);
if (check_error(shader, GL_LINK_STATUS, true)) {
    LOGE("Failed to link shader");
}

glValidateProgram(shader);
if (check_error(shader, GL_VALIDATE_STATUS, true)) {
    LOGE("Failed to validate shader");
}

Error Checking Code:

static bool check_error(unsigned int shader, unsigned int param, bool isProgram) {
int res = 123;
char log[2048] = { 0 };
if (isProgram) {
    glGetProgramiv(shader, param, &res);
    if (res == 0) {
        glGetProgramInfoLog(shader, sizeof(log), 0, log);
        LOGE("Shader: %s", log);
        return true;
    }
} else {
    glGetShaderiv(shader, param, &res);
    if (res == 0) {
        glGetShaderInfoLog(shader, sizeof(log), 0, log);
        LOGD("Shader %s", log);
        return true;
    }
}

return false;
}

Everything compiles just fine. But when I later call glGetAttribLocation to get the index of position, it return -1. I've also tried binding it before linking with glBindAttribLocation.

Querying all attributs with glGetActiveAttrib just return some junk. Same goes for the uniform "color" in the fragment shader.

I've tried running it on my phone (Galaxy S3) and on the Visual Studio Emulator For Android, same result on both of them.

My guess is that they get optimized out, but they shouldn't since I'm clearly using them and they contribute to the output.

Thanks in advance!

JeppeSRC
  • 89
  • 1
  • 9
  • Maybe post your check_error code? Perhaps there's a bug in there and the link has failed. In particular, is your check_error function calling glGetShaderiv? To check the link was successful it needs to call glGetProgramiv. – Columbo Jun 08 '17 at 21:28
  • glGetShaderiv and glGetProgramiv both return 1. The error checking works, it correctly report errors if I do something wrong. – JeppeSRC Jun 09 '17 at 05:04
  • Possible duplicate of [glGetAttribLocation returns -1 when retrieving existing shader attribute](https://stackoverflow.com/questions/15639957/glgetattriblocation-returns-1-when-retrieving-existing-shader-attribute) – James Poag Jun 09 '17 at 10:42
  • Is it possible the context isn't bound when you call glGetAttribLocation? (perhaps because it's on another thread). Does it work if you try calling it immediately after the glLinkProgram rather than calling it 'later'. FWIW, I don't think it can be an optimization problem, position and color are both clearly in use. – Columbo Jun 09 '17 at 15:41
  • No, the context is bound. If it's not an optimization problem then what is it? – JeppeSRC Jun 09 '17 at 19:34
  • I expect it's a bug somewhere in code that isn't posted (probably of the silly typo variety that we all make from time to time). I suggest you post the code that calls glGetShaderiv and glGetProgramiv and glGetAttribLocation, and the code that populates 'vertex' and 'fragment'. Or even better make a minimal, complete and verifiable example - probably in the process of doing so you'll discover the problem yourself. – Columbo Jun 10 '17 at 07:09
  • The code use to check for errors is now in the question. The content of 'vertex' and 'fragment' is just a string with the content above. – JeppeSRC Jun 10 '17 at 09:31

2 Answers2

1

It's exactly as Columbo said in the comments, it's just a stupid misstake by me. I created a new variable to hold the program id instead of using the one I declared in the class. Which was the one I later used in the calls to glGetAttribLocation and glUseProgram.

JeppeSRC
  • 89
  • 1
  • 9
0

After you compile the shaders and before you link them, you need to explicitly bind the attribute locations using glBindAttribLocation.

After you bind the locations, link the program.

Later, bind directly to the location you specified using glVertexAttribPointer (be sure to enable the stream with `glEnableVertexAttribArray).

Don't query, just set. If you want to query, make sure that the shader program is enabled and the streams are bound and activated first.

James Poag
  • 2,320
  • 1
  • 13
  • 20
  • 1
    I don't need to bind them. The linker will bind those I don't explicitly bind. And I've tried explicitly binding them just in case the linker didn't. – JeppeSRC Jun 08 '17 at 16:15
  • https://stackoverflow.com/questions/15639957/glgetattriblocation-returns-1-when-retrieving-existing-shader-attribute – James Poag Jun 09 '17 at 10:42
  • That's not relevant, I'm using it in the shader so it shouldn't be optimized away. And I've tested binding it my self before linking. – JeppeSRC Jun 09 '17 at 10:45
  • You aren't `using` it. You're just copying it. – James Poag Jun 09 '17 at 11:31
  • Then how am I supposed to do it? – JeppeSRC Jun 09 '17 at 12:18
  • If copying it to the output isn't sufficient, then that must be the dummest thing ever. I'll try multiplying it with some matrix so that m not just copying it. – JeppeSRC Jun 09 '17 at 12:24
  • Or the smartest thing ever. I have shaders that I do multiple calculations against uniforms and attributes. The second I stop writing the results to outputs (say, when I'm debugging) then the compiler optimizes it all out. If you read the link I provided, it suggests that you not rely on `glGetAttribLocation`, especially with optimizing compilers. – James Poag Jun 09 '17 at 12:50