nicolasgramlich / AndEngine

Free Android 2D OpenGL Game Engine
http://www.andengine.org
Apache License 2.0
3.17k stars 1.35k forks source link

ShaderProgramException #31

Closed sjvc closed 12 years ago

sjvc commented 12 years ago

Someone sent me that error report of my game (Juggle The Doodle):

org.andengine.opengl.shader.exception.ShaderProgramException: Unexpected uniform: 'u_modelViewProjectionMatrix'. at org.andengine.opengl.shader.ShaderProgram.getUniformLocation(ShaderProgram.java:99) at org.andengine.opengl.shader.PositionColorTextureCoordinatesShaderProgram.link(PositionColorTextureCoordinatesShaderProgram.java:83) at org.andengine.opengl.shader.ShaderProgram.compile(ShaderProgram.java:149) at org.andengine.opengl.shader.ShaderProgram.bind(ShaderProgram.java:122) at org.andengine.opengl.shader.PositionColorTextureCoordinatesShaderProgram.bind(PositionColorTextureCoordinatesShaderProgram.java:89) at org.andengine.opengl.vbo.VertexBufferObject.bind(VertexBufferObject.java:150) at org.andengine.entity.sprite.Sprite.preDraw(Sprite.java:175) at org.andengine.entity.Entity.onManagedDraw(Entity.java:1181) at org.andengine.entity.shape.Shape.onManagedDraw(Shape.java:123) at org.andengine.entity.Entity.onDraw(Entity.java:1009) at org.andengine.entity.Entity.onManagedDrawChildren(Entity.java:1203) at org.andengine.entity.Entity.onDrawChildren(Entity.java:1195) at org.andengine.entity.Entity.onManagedDraw(Entity.java:1185) at org.andengine.entity.scene.Scene.onManagedDraw(Scene.java:262) at org.andengine.entity.Entity.onDraw(Entity.java:1009) at org.andengine.entity.scene.Scene.onManagedDraw(Scene.java:269) at org.andengine.entity.Entity.onDraw(Entity.java:1009) at org.andengine.engine.Engine.onDrawScene(Engine.java:560) at org.andengine.engine.Engine.onDrawFrame(Engine.java:552) at org.andengine.opengl.view.EngineRenderer.onDrawFrame(EngineRenderer.java:104) at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1363) at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1118)

sjvc commented 12 years ago

With latest AndEngine version, I received this one:

org.andengine.opengl.shader.exception.ShaderProgramException: Unexpected uniform: 'u_modelViewProjectionMatrix'. Existing uniforms: {u_modelViewProjectionMatrix=-1} at org.andengine.opengl.shader.ShaderProgram.getUniformLocation(ShaderProgram.java:99) at org.andengine.opengl.shader.PositionColorShaderProgram.link(PositionColorShaderProgram.java:76) at org.andengine.opengl.shader.ShaderProgram.compile(ShaderProgram.java:149) at org.andengine.opengl.shader.ShaderProgram.bind(ShaderProgram.java:122) at org.andengine.opengl.shader.PositionColorShaderProgram.bind(PositionColorShaderProgram.java:83) at org.andengine.opengl.vbo.VertexBufferObject.bind(VertexBufferObject.java:155) at org.andengine.entity.primitive.Rectangle.preDraw(Rectangle.java:98) at org.andengine.entity.Entity.onManagedDraw(Entity.java:1226) at org.andengine.entity.Entity.onDraw(Entity.java:1032) at org.andengine.entity.Entity.onManagedDraw(Entity.java:1255) at org.andengine.entity.scene.Scene.onManagedDraw(Scene.java:261) at org.andengine.entity.Entity.onDraw(Entity.java:1032) at org.andengine.engine.Engine.onDrawScene(Engine.java:599) at org.andengine.engine.Engine.onDrawFrame(Engine.java:589) at org.andengine.opengl.view.EngineRenderer.onDrawFrame(EngineRenderer.java:104) at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1363) at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1118)

walidhalabi commented 12 years ago

I've gotten this a few times too. I don't use anything GLES2 specific like shaders - I ported my GLES1 game over.

Here's my stack trace:

org.andengine.opengl.shader.exception.ShaderProgramException: Unexpected uniform: 'u_modelViewProjectionMatrix'. Existing uniforms: {u_texture_0=-1, u_modelViewProjectionMatrix=-1} at org.andengine.opengl.shader.ShaderProgram.getUniformLocation(SourceFile:99) at org.andengine.opengl.shader.PositionColorTextureCoordinatesShaderProgram.link(SourceFile:83) at org.andengine.opengl.shader.ShaderProgram.bind(SourceFile:122) at org.andengine.opengl.shader.PositionColorTextureCoordinatesShaderProgram.bind(SourceFile:89) at org.andengine.opengl.vbo.VertexBufferObject.bind(SourceFile:155) at org.andengine.entity.sprite.Sprite.preDraw(SourceFile:170) at org.andengine.entity.Entity.onManagedDraw(SourceFile:1227) at org.andengine.entity.Entity.onDraw(SourceFile:1033) at org.andengine.entity.Entity.onManagedDraw(SourceFile:1256) at org.andengine.entity.scene.Scene.onManagedDraw(SourceFile:262) at org.andengine.entity.Entity.onDraw(SourceFile:1033) at org.andengine.engine.camera.Camera.onDrawHUD(SourceFile:268) at org.andengine.engine.Engine.onDrawFrame(SourceFile:589) at org.andengine.opengl.view.EngineRenderer.onDrawFrame(SourceFile:104) at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1363) at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1118)

allanharris commented 12 years ago

Got same errors at Android Market today: this: java.lang.IllegalArgumentException: No EGLConfig found! at org.andengine.opengl.view.h.a(Unknown Source) at org.andengine.opengl.view.h.chooseConfig(Unknown Source) at android.opengl.GLSurfaceView$EglHelper.start(GLSurfaceView.java:951) at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1281) at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1151)

and this: org.andengine.opengl.c.a.b: Unexpected uniform: 'umodelViewProjectionMatrix'. at org.andengine.opengl.c.d.a(Unknown Source) at org.andengine.opengl.c.b.a(Unknown Source) at org.andengine.opengl.c.d.a(Unknown Source) at org.andengine.opengl.c.b.a(Unknown Source) at org.andengine.opengl.b.e.a(Unknown Source) at org.andengine.d.d.d.a(Unknown Source) at org.andengine.d.f.c(Unknown Source) at org.andengine.d.f.a(Unknown Source) at org.andengine.d.b.b.a.a(Unknown Source) at org.andengine.d.b.a.c(Unknown Source) at org.andengine.d.f.a(Unknown Source) at org.andengine.e.c.a(Unknown Source) at org.andengine.opengl.view.c.onDrawFrame(Unknown Source) at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1363) at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1118)

Sorry for obfuscated code

walidhalabi commented 12 years ago

Any word Nicolas? I'm getting this a lot. Can I provide any further information to help?

kocus commented 12 years ago

Got the same shader program exception (Android Market stacktrace bellow):

org.andengine.opengl.shader.exception.ShaderProgramException: Unexpected uniform: 'u_modelViewProjectionMatrix'. Existing uniforms: {u_texture_0=-1, u_modelViewProjectionMatrix=-1} at org.andengine.opengl.shader.ShaderProgram.getUniformLocation(SourceFile:99) at org.andengine.opengl.shader.PositionColorTextureCoordinatesShaderProgram.link(SourceFile:83) at org.andengine.opengl.shader.ShaderProgram.bind(SourceFile:122) at org.andengine.opengl.shader.PositionColorTextureCoordinatesShaderProgram.bind(SourceFile:89) at org.andengine.opengl.vbo.VertexBufferObject.onBufferData(SourceFile:155) bind at org.andengine.entity.sprite.Sprite.preDraw(SourceFile:174) at org.andengine.entity.Entity.onManagedDraw(SourceFile:1227) at org.andengine.entity.Entity.onDraw(SourceFile:1033) at org.andengine.entity.scene.background.EntityBackground.onDraw(SourceFile:50) at org.andengine.entity.scene.Scene.onManagedDraw(SourceFile:253) at org.andengine.entity.Entity.onDraw(SourceFile:1033) at org.andengine.engine.Engine.onDrawFrame(SourceFile:589) at org.andengine.opengl.view.GLSurfaceView$GLThread.guardedRun(SourceFile:1473) at org.andengine.opengl.view.GLSurfaceView$GLThread.run(SourceFile:1220)

Any ideas? This seems to happen only on some devices, I've tested my program in many ways, and never got this issue.

walidhalabi commented 12 years ago

Here's a list of devices that got this exception lately:

ZTE-T U880 ZTE-T U880 HUAWEI T8300 HUAWEI T8300 HUAWEI T8300 HUAWEI T8300 VB734 HUAWEI T8600 HUAWEI T8600 HUAWEI T8600 ARMM7 T-91 T-91 T-91 T-91 T-91 GT-I9100 GT-I9100 ZTE-T U830 ZTE-T U830 GT-S5820 HUAWEI T8300 Lenovo A66t Lenovo A66t Lenovo A66t GT-S5820 GT-S5820 GT-S5820 GT-S5820 GT-S5820 GT-S5820 HUAWEI T8600 HUAWEI T8600

I can get more, and also have full build details for each

Can we get a response to this please? Even if it's "I'm too busy"?

kocus commented 12 years ago

Any luck tracking this issue?

kocus commented 12 years ago

It looks that I've managed to fixed that issue! The problem is that, some drivers badly indicate the LENGTH of the shader uniform variable. The function GLES20.glGetActiveUniform() return the length + 1 for some phones. Then, we have variable "u_texture_0", but we are trying to find the location of "u_texture_0 " (notice the additional space at the end!) using GLES20.glGetUniformLocation() which returns -1. Next, we are inserting this pair into HashMap : mUniformLocations - and that's the reason, why it contains uniforms: {u_texture_0 =-1, u_modelViewProjectionMatrix =-1} (with space in names!).

The fix is pretty obvious: In the file: org.andengine.opengl.shader.ShaderProgram the function initUniformLocations should look like this:

private void initUniformLocations() {
    this.mUniformLocations.clear();

    ShaderProgram.PARAMETERS_CONTAINER[0] = 0;
    GLES20.glGetProgramiv(this.mProgramID, GLES20.GL_ACTIVE_UNIFORMS, ShaderProgram.PARAMETERS_CONTAINER, 0);
    final int numUniforms = ShaderProgram.PARAMETERS_CONTAINER[0];

    for(int i = 0; i < numUniforms; i++) {
        GLES20.glGetActiveUniform(this.mProgramID, i, ShaderProgram.NAME_CONTAINER_SIZE, ShaderProgram.LENGTH_CONTAINER, 0, ShaderProgram.SIZE_CONTAINER, 0, ShaderProgram.TYPE_CONTAINER, 0, ShaderProgram.NAME_CONTAINER, 0);

        int length = ShaderProgram.LENGTH_CONTAINER[0];
        /* Some drivers do not report the actual length here, but zero. Then the name is '\0' terminated. */
        if(length == 0) {
            while(length < NAME_CONTAINER_SIZE && ShaderProgram.NAME_CONTAINER[length] != '\0') {
                 length++;
            }
        }
        String name = new String(ShaderProgram.NAME_CONTAINER, 0, length);
        // the "name" shouldn't contain spaces at the end. If it does, delete all of them
        if (name.contains(" ")){
            name = name.substring(0, name.indexOf(" "));
        }

        final int location = GLES20.glGetUniformLocation(this.mProgramID, name);
        this.mUniformLocations.put(name, location);
    }
}

Also, the function initAttributeLocations should be fixed in the same way as well. I will check via next app update, if this resolve the issue. It's rather quick fix, maybe somebody can manage to make prettier solution :)

walidhalabi commented 12 years ago

Great find! How sure are you that this is the issue?

Also, would using String.trim be simpler? http://developer.android.com/reference/java/lang/String.html#trim()

kocus commented 12 years ago

I have done some syntetic tests, and it looks like this is the issue. But have to wait couple days to be sure - our app on the AM had about 20 crashed per day caused by this ShaderProgramException.

About trim() - I didn't know that this kind of function exists - thx :)

EDIT: It's not the space on the end, the name is terminated with '\0', but the length is +1. So basically we just need to always count the number of chars.

kocus commented 12 years ago

Okay, this solution looks much more promising:

private void initUniformLocations() {
    this.mUniformLocations.clear();

    ShaderProgram.PARAMETERS_CONTAINER[0] = 0;
    GLES20.glGetProgramiv(this.mProgramID, GLES20.GL_ACTIVE_UNIFORMS, ShaderProgram.PARAMETERS_CONTAINER, 0);
    final int numUniforms = ShaderProgram.PARAMETERS_CONTAINER[0];

    for(int i = 0; i < numUniforms; i++) {
        GLES20.glGetActiveUniform(this.mProgramID, i, ShaderProgram.NAME_CONTAINER_SIZE, ShaderProgram.LENGTH_CONTAINER, 0, ShaderProgram.SIZE_CONTAINER, 0, ShaderProgram.TYPE_CONTAINER, 0, ShaderProgram.NAME_CONTAINER, 0);

        int length = ShaderProgram.LENGTH_CONTAINER[0];
        /* Some drivers do not report the actual length here, but zero. Then the name is '\0' terminated. */
        if(length == 0) {
            while(length < NAME_CONTAINER_SIZE && ShaderProgram.NAME_CONTAINER[length] != '\0') {
                 length++;
            }
        }
        String name = new String(ShaderProgram.NAME_CONTAINER, 0, length);
        int location = GLES20.glGetUniformLocation(this.mProgramID, name);

        // failsafe, location is invalid - probably the glGetActiveUniform() return the invalid length. calculate it manually.
        if (location == -1){
            length = 0;
            while(length < NAME_CONTAINER_SIZE && ShaderProgram.NAME_CONTAINER[length] != '\0') {
                 length++;
            }

            name = new String(ShaderProgram.NAME_CONTAINER, 0, length);
            location = GLES20.glGetUniformLocation(this.mProgramID, name);
        }

        this.mUniformLocations.put(name, location);
    }
}
walidhalabi commented 12 years ago

Ahh i see

Great work! Let us know how you go

I was starting to despair about andengine again because of this bug :)

kocus commented 12 years ago

Seems that the last fix proposed by me works pretty well - I've got no bug report since that:)

DrDerico commented 12 years ago

Thank you!

nicolasgramlich commented 12 years ago

Merged into AndEngine: 8f7f5e026ec2c95ea45a32a302b21bc92bfcb722

Please alert me for issues serious like this by mail - or file a pull request, which receive more attention than issues itself.

Thanks!

walidhalabi commented 12 years ago

Thanks!