1
\$\begingroup\$

I'm programming an app with OpenGL ES on Android in Java. The app uses 9 textures during a render loop pass. A depth, position, normal, albedo, noise, SSAO, SSAO blur and two image textures for the models I draw. The problem is that 9/10 times, the image textures fail to load. I get no GL error during or after loading the texture. I get an error 1282 when I bind the texture 8 and 9 during the draw call. But only when they don't load/show up. When they load and show up I get no error and they are displayed correctly on the primitives.

enter image description here enter image description here

According to the documentation of glBindTexture, the method generates the error code 1282 (GL_INVALID_OPERATION) if texture was previously created with a target that doesn't match that of the target. The only target I use in the whole application is GL_TEXTURE_2D, so I don't understand why I get this error.

Since I'm using a deferred rendering pipeline, I thought that maybe the albedo buffer is messed up, but I could rule that out by setting constant colors for the whole scene directly in the fragment shader of the geometry pass, and that is working fine every time.

I managed to take GPU-snapshots of both cases using snapdragon profiler to debug the app/profile the GPU (Adreno 630). I could verify that all the uniforms are correct, the attribute arrays are also correct and the correct units are active in both cases. The difference I could notice in the error case is that both image textures are missing, the rest is there. These are all the textures on the GPU when they load:

enter image description here

Here, in the other snapshot they are missing, even though it is the exact same code that loads the textures. In both cases I get valid handles/indexes when I call glGenTexture.

enter image description here

It just seems that somehow the textures aren't loaded anymore during the draw call.

The image textures are being loaded like this:

AssetManager assetManager = context.getAssets();
InputStream stream = assetManager.open(id.getResourceName());
int[] textureHandle = new int[1];

BitmapFactory.Options option = new BitmapFactory.Options();
option.inScaled = false;
Bitmap bitmap = BitmapFactory.decodeStream(stream, null, option);
//GLES30.glActiveTexture(GLES30.GL_TEXTURE5);
GLES30.glGenTextures(1, textureHandle, 0);
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textureHandle[0]);
GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_NEAREST);
GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR);
GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_MIRRORED_REPEAT);
GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_MIRRORED_REPEAT);
if (bitmap != null) {
    Log.d(TextureLoader.class.getSimpleName(), "Texture format: " + GLUtils.getInternalFormat(bitmap));
    GLUtils.texImage2D(GLES30.GL_TEXTURE_2D, 0, bitmap, 0);
    bitmap.recycle();
}
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, 0);
        
ShaderUtil.checkGLError(TextureLoader.class.getSimpleName(), "Failed to load texture");

Log.d("Texture id", String.valueOf(textureHandle[0]));

return textureHandle[0];
  • The code above is executed during the onSurfaceCreated invocation, so I have a valid OpenGL context.
  • The code above is executed two times, once per image texture in sequential order.
  • Both textures are of type 32 bit RGBA (PNG) 512px x 512px

The code below is executed in the render loop. I have multiple models, some are using one texture and some the other one.

GLES30.glActiveTexture(GLES30.GL_TEXTURE5);
GLES30.glUniform1i(shaderHandles.getTextureMapHandle(), 5);
ShaderUtil.checkGLError("Render loop", "Activate unit");
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textureDataHandle);
ShaderUtil.checkGLError("Render loop", "Activate " + textureDataHandle);

I've been debugging for multiple days now, so I appreciate any help. Thank you

Edit: Some new discoveries i made were, that if I load the textures before I create the all the frame buffers for shadow mapping and SSAO, I get the content of the shadow map texture on one model (just the red channel) and the position buffer as rgb content of the other model. That happens since I get index 1 & 2 for the image textures from open gl, but the depth, position, ... texture restart at 1 with indexing. And then I bind the texture with index 1 & 2 as model textures, which happen to be the depth texture and the position texture. I just dont understand why the indexing restarts.

Edit 2: Using the profiler I found out that I have two contexts and the image textures are loaded in the other context. Why am I having two contexts?

enter image description here

\$\endgroup\$
4
  • \$\begingroup\$ Could you show the code that calls the function to load the textures ? Considering the same code sometimes works and sometimes doesn't, have you considered the possibility of a race condition happening? Are you loading your textures in a background thread, while having the main thread call glBindTexture or something like that? \$\endgroup\$ Commented Dec 6, 2023 at 10:11
  • \$\begingroup\$ Thank you for your help. Its pretty nested, so i would have to show/explain a lot. Yeah, I thought of that too, but I'm not making use of any parallel programming paradigms. Everything is in sequential order executing on the open gl thread (execution begins in the onSurfaceCreated method). The models i draw are created in sequential order (simple foreach loop) which implies, the textures are also being loaded sequentially. And afterwards they are accessed in the the draw calls (onDrawFrame invocation). \$\endgroup\$
    – Patrick
    Commented Dec 6, 2023 at 11:16
  • \$\begingroup\$ Have you tried using logcat to see if any errors pop-up when the textures are not loading? \$\endgroup\$ Commented Dec 6, 2023 at 14:54
  • \$\begingroup\$ Yeah, like I stated in the question, I get no error when loading the textures but I get an error when i bind them in the draw call. FYI I edited the question. I was able to narrow down the problem. \$\endgroup\$
    – Patrick
    Commented Dec 6, 2023 at 15:20

1 Answer 1

0
\$\begingroup\$

I figuerd out why the texture loading was not working. I had two glSurfaceView in two fragments in my project.

Switching from one to another messed the EGL context up and created a race condition where the texture loaded on the current context and sometimes on the old context. Im not sure if it was the old context or another one that was created just in the onSurfaceCreated callback.

I solved it by creating my own SurfaceViews and managing the context, render thread, ... by my self.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .