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:
- https://blog.dengine.net/2021/01/wonders-and-mysteries-of-the-m1/
- https://bugreports.qt.io/browse/QTBUG-89803
- https://bugreports.qt.io/browse/QTBUG-97981
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 if
s 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?