Question

System: Android 4.03, OpenGL ES 2.0

Problem: When glAttachShader is invoked after the first frame has already been rendered with another program / shader, some devices (Galaxy S3) crash with a "GL_INVALID_VALUE" error (no further details are available in the error stack). Other devices (Asus eee TF101) are perfectly fine with that. The error does not always occur and sometimes it's also a "GL_INVALID_ENUM" instead. If I force all shaders to be compiled right at the first call to onDrawFrame, it works on all (my) devices.

Questions: Are there states in which the openGL(ES) machine is incapable of compiling a shader? Is it possible that bound buffers, textures or enabled attribute arrays interfere with attaching a shader to a program? If so, what is the ideal state one must ensure before attaching shaders and linking the program? Is it even valid to compile shaders after other objects have already been rendered with other shaders?

Background: I'm developing an Android library that will allow me to use openGL graphics in a more object oriented way (using objects like "scene", "material", "model" etc.), utlimatively to write games easily. The scenes, models etc. are created in a thread different to the GL context. Only when onDrawFrame encounters one of these objects it will do the buffer object binding, texture binding and shader compilation, within the right thread. I would like to avoid to compile all shaders at the beginning of my code. The shader source is assembled depending on the requirements of the material, the model and the scene (eg: Material: include bump-mapping, Model: include matrix-palette-skimming, scene: include fog). When a model is removed from a scene, I'm going to delete the shader again - and if I add another model, the new shader should be compiled ad-hoc.

At this point I'm trying to be as concise as possible without posting code - you can imagine that extracting the relevant parts from this library is difficult.

Was it helpful?

Solution 2

If you copy the BasicGLSurfaceView sample code that comes with the Android development kit to start your project, then the first call to

checkGlError

is after attaching the vertex shader. However, you might have used an invalid value or enum a lot earlier or in a different location in your code. But this will only be picked up by this call, after glAttachShader.

In my case I deleted a texture which was still linked as render target for a framebuffer. My older Android device which runs slower compiled the shader before deleting, my newer device somehow managed to call

glFramebufferTexture2D

before compiling the shader. The whole thing somehow links to queueEvent and my poor understanding of thread-safety.

Thanks for your efforts, TraxNet and Prateek Nina.

OTHER TIPS

It is perfectly valid to compile during rendering although is discouraged as the driver needs to take resources (CPU) for that. Some driver states my trigger a shader recompile at the driver side as some states are injected into the shader. It wise to reorganize your drawing calls into chunks sharing the same driver state (preferred by shader program as is one of the most expensive operations done by the driver).

TIP: Be sure to "use" all variables, uniforms and attribs declared into your shader, otherwise, the Mali driver removes them during compile and when you try to get an uniform location, an attrib location and son on, the drivers returns GL_INVALID_VALUE.

Hope that helps.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top