6

Let's first acknowledge that OpenGL is deprecated by Apple, that the last supported version is 4.1 and that that's a shame but hey, we've got to move forward somehow and Vulkan is the way :trollface: Now that that's out of our systems, let's have a look at this weird bug I found. And let me be clear that I am running this on an Apple Silicon M1, late 2020 MacBook Pro with macOS 11.6. Let's proceed.

I've been following LearnOpenGL and I have published my WiP right here to track my progress. All good until I got to textures. Using one texture was easy enough so I went straight into using more than one, and that's when I got into trouble. As I understand it, the workflow is more or less

  • load pixel data in a byte array called textureData, plus extra info
  • glGenTextures(1, &textureID)
  • glBindTexture(GL_TEXTURE_2D, textureID)
  • set parameters at will
  • glTexImage2D(GL_TEXTURE_2D, ... , textureData)
  • glGenerateMipmap(GL_TEXTURE_2D) (although this may be optional)

which is what I do around here, and then

  • glUniform1i(glGetUniformLocation(ID, "textureSampler"), textureID)
  • rinse and repeat for the other texture

and then, in the drawing loop, I should have the following:

  • glUseProgram(shaderID)
  • glActiveTexture(GL_TEXTURE0)
  • glBindTexture(GL_TEXTURE_2D, textureID)
  • glActiveTexture(GL_TEXTURE1)
  • glBindTexture(GL_TEXTURE_2D, otherTextureID)

I then prepare my fancy fragment shader as follows:

#version 410 core

out vec4 FragColor;
in vec2 TexCoord;

uniform sampler2D textureSampler;
uniform sampler2D otherTextureSampler;

void main() {
    if (TexCoord.x < 0.5) {
        FragColor = texture(textureSampler, TexCoord);
    } else {
        FragColor = texture(otherTextureSampler, TexCoord);
    }
}

and I should have a quad on screen with a texture made up by textureSampler on its left half, and otherTextureSampler on its right half. Instead, I have otherTextureSampler on the left half, black on the other half, and a log message that says

UNSUPPORTED (log once): POSSIBLE ISSUE: unit 1 GLD_TEXTURE_INDEX_2D is unloadable and bound to sampler type (Float) - using zero texture because texture unloadable

I've been on this bug's trail for two days now and there just isn't very much on the Internet. Some reports point to a possible bug in Apple's GLSL compiler, some others point to the need for binding an extra texture for no apparent reason. These three are the most relevant pieces of information I managed to find:

However, none of these helped me very much. Until I did something without thinking. The eagle-eyed among you will have noticed that the drawing code in my git repo is slightly different. It says right here that I am in fact using GL_TEXTURE1 and GL_TEXTURE2.

It was my understanding that 0 and 1 were the two texture units that I was activating and binding, so why does using texture units 1 and 2 yield the expected result?

I tried to add calls to glActiveTexture(GL_TEXTURE0) and 1 right after generating the textures and before binding them, but with zero success. I also tried using a sampler array like this person suggests and going in with a bunch of ifs and integer indices, but of course I was still getting the wrong result.

I spent a few hours trying every possible combination and the only practical "solution" is to use "+1" texture units, as in GL_TEXTUREn with n >= 1.

Question: with all the caveat expressed in the very first paragraph, who is doing something wrong here? Is it noob me who's trying to learn decades old technology on modern hardware, or is it genuinely a bug in Apple's implementation of OpenGL or the GLSL compiler, and so there's zero chance of having it fixed and I should just get on with my "special hardware manufacturer's" crutches?

Morpheu5
  • 2,610
  • 6
  • 39
  • 72
  • 7
    No, `glUniform1i` for a `sampler2D` doesn't accept a texture handle, but rather a texture slot index. So if you did `glActiveTexture(GL_TEXTUREn)` before binding the texture, you pass `n` to `glUniform1i`. – HolyBlackCat Dec 13 '21 at 18:01
  • 1
    ... so in your case it has to be `glUniform1i(glGetUniformLocation(ID, "textureSampler"), 0)`, because the texture object `textureID` is bound to the texture unit 0 (`GL_TEXTURE0`). – Rabbid76 Dec 13 '21 at 18:05
  • Now, how stupid do I feel from one to holy f#ck? I went back to the website and it turns out I misread this: "Using `glUniform1i` we can actually assign a *location* value to the texture sampler". I read that and assumed he meant the texture ID. OK, mystery solved, I guess? – Morpheu5 Dec 13 '21 at 18:07
  • I'm waiting so I can give you a green tick :) – Morpheu5 Dec 13 '21 at 18:15

3 Answers3

6

Instead of passing a texture handle to glUniform1i(glGetUniformLocation(ID, "textureSampler"), ...), you need to pass a texture slot index.

E.g. if you did glActiveTexture(GL_TEXTUREn) before binding the texture, pass n.

HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207
2

I know this has been answered for this particular case, although I've been having the same error message even after setting correctly the glsl uniform texture binding ("unit 0 GLD_TEXTURE_INDEX_2D is unloadable and bound to sampler type (Float)").

I'm also on a Mac M1, using OpenGL 2.1 I had a wrong parameter set for the texture sampler (GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR, but no mipmap was bound) and setting a "good" one solved the issue.

Rationale for other devs having the same error message : also check that texture sampler parameters are correct.

Cheers

brainsandwich
  • 472
  • 3
  • 10
0

An invalid image, an empty data set for example, can cause this. I had this issue some time ago and in my case the file path was wrong.