InstanceNode get exception on Android with jme3.1-stable

I tried InstanceNode on desktop after read this thread.

It works amazing fast. So I test it again on Android, then I get exceptions. Commom/ShadeLib/Instance.glsllib may be have some problem on GLES. #635

Here are the exceptions.

E/com.jme3.util.BufferUtils: SEVERE {0}
                         java.lang.IllegalArgumentException: Expected receiver of type sun.nio.ch.DirectBuffer, but got java.nio.ByteBufferAsFloatBuffer
                             at java.lang.reflect.Method.invoke(Native Method)
                             at com.jme3.util.BufferUtils.destroyDirectBuffer(BufferUtils.java:1330)
                             at com.jme3.scene.instancing.InstancedGeometry.setMaxNumInstances(InstancedGeometry.java:196)
                             at com.jme3.scene.instancing.InstancedGeometry.addInstance(InstancedGeometry.java:322)
                             at com.jme3.scene.instancing.InstancedNode.addToInstancedGeometry(InstancedNode.java:239)
                             at com.jme3.scene.instancing.InstancedNode.instance(InstancedNode.java:293)
                             at com.jme3.scene.instancing.InstancedNode.instance(InstancedNode.java:300)
                             at com.jme3.scene.instancing.InstancedNode.instance(InstancedNode.java:306)
                             at net.jmecn.mygame.TestInstanceNode.simpleInitApp(TestInstanceNode.java:94)
                             at com.jme3.app.SimpleApplication.initialize(SimpleApplication.java:220)
                             at com.jme3.app.AndroidHarness.initialize(AndroidHarness.java:478)
                             at com.jme3.system.android.OGLESContext.onDrawFrame(OGLESContext.java:328)
                             at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1548)
                             at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1259)
W/com.jme3.renderer.opengl.GLRenderer: WARNING Bad compile of:
                                   1	#version 100
                                   2	#define VERTEX_SHADER 1
                                   3	#define INSTANCING 1
                                   4	#define HAS_COLOR 1
                                   5	// -- begin import Common/ShaderLib/GLSLCompat.glsllib --
                                   6	#if defined GL_ES
                                   7	#  define hfloat highp float
                                   8	#  define hvec2  highp vec2
                                   9	#  define hvec3  highp vec3
                                   10	#  define hvec4  highp vec4
                                   11	#  define lfloat lowp float
                                   12	#  define lvec2 lowp vec2
                                   13	#  define lvec3 lowp vec3
                                   14	#  define lvec4 lowp vec4
                                   15	#else
                                   16	#  define hfloat float
                                   17	#  define hvec2  vec2
                                   18	#  define hvec3  vec3
                                   19	#  define hvec4  vec4
                                   20	#  define lfloat float
                                   21	#  define lvec2  vec2
                                   22	#  define lvec3  vec3
                                   23	#  define lvec4  vec4
                                   24	#endif
                                   25	
                                   26	#if __VERSION__ >= 130
                                   27	out vec4 outFragColor;
                                   28	#  define texture1D texture
                                   29	#  define texture2D texture
                                   30	#  define texture3D texture
                                   31	#  define texture2DLod texture
                                   32	#  if defined VERTEX_SHADER
                                   33	#    define varying out
                                   34	#    define attribute in
                                   35	#  elif defined FRAGMENT_SHADER
                                   36	#    define varying in
                                   37	#    define gl_FragColor outFragColor
                                   38	#  endif
                                   39	#endif
                                   40	// -- end import Common/ShaderLib/GLSLCompat.glsllib --
                                   41	// -- begin import Common/ShaderLib/Skinning.glsllib --
                                   42	#ifdef NUM_BONES
                                   43	
                                   44	#if NUM_BONES < 1 || NUM_BONES > 255
                                   45	#error NUM_BONES must be between 1 and 255.
                                   46	#endif
                                   47	
                                   48	#define NUM_WEIGHTS_PER_VERT 4
                                   49	 
                                   50	attribute vec4 inHWBoneWeight;
                                   51	attribute vec4 inHWBoneIndex;
                                   52	uniform mat4 m_BoneMatrices[NUM_BONES];
                                   53	
                                   54	void Skinning_Compute(inout vec4 position){
                                   55	    if (inHWBoneWeight.x != 0.0) {
                                   56	#if NUM_WEIGHTS_PER_VERT == 1
                                   57	        position = m_BoneMatrices[int(inHWBoneIndex.x)] * position;
                                   58	#else
                                   59	        mat4 mat = mat4(0.0);
                                   60	        mat += m_BoneMatrices[int(inHWBoneIndex.x)] * inHWBoneWeight.x;
                                   61	        mat += m_BoneMatrices[int(inHWBoneIndex.y)] * inHWBoneWeight.y;
                                   62	        mat += m_BoneMatrices[int(inHWBoneIndex.z)] * inHWBoneWeight.z;
                                   63	        mat += m_BoneMatrices[int(inHWBoneIndex.w)] * inHWBoneWeight.w;
                                   64	        position = mat * position;
                                   65	#endif
                                   66	    }
                                   67	}
                                   68	 
                                   69	void Skinning_Compute(inout vec4 position, inout vec3 normal){
                                   70	    if (inHWBoneWeight.x != 0.0) {
                                   71	#if NUM_WEIGHTS_PER_VERT == 1
                                   72	        position = m_BoneMatrices[int(inHWBoneIndex.x)] * position;
                                   73	        normal = (mat3(m_BoneMatrices[int(inHWBoneIndex.x)][0].xyz,
                                   74	                       m_BoneMatrices[int(inHWBoneIndex.x)][1].xyz,
                                   75	                       m_BoneMatrices[int(inHWBoneIndex.x)][2].xyz) * normal);
                                   76	#else
                                   77	        mat4 mat = mat4(0.0);
                                   78	        mat += m_BoneMatrices[int(inHWBoneIndex.x)] * inHWBoneWeight.x;
                                   79	        mat += m_BoneMatrices[int(inHWBoneIndex.y)] * inHWBoneWeight.y;
                                   80	        mat += m_BoneMatrices[int(inHWBoneIndex.z)] * inHWBoneWeight.z;
                                   81	        mat += m_BoneMatrices[int(inHWBoneIndex.w)] * inHWBoneWeight.w;
                                   82	        position = mat * position;
                                   83	
                                   84	        mat3 rotMat = mat3(mat[0].xyz, mat[1].xyz, mat[2].xyz);
                                   85	        normal = rotMat * normal;
                                   86	#endif
                                   87	    }
                                   88	}
                                   89	 
                                   90	void Skinning_Compute(inout vec4 position, inout vec3 tangent, inout vec3 normal){
                                   91	    if (inHWBoneWeight.x != 0.0) {
                                   92	#if NUM_WEIGHTS_PER_VERT == 1
                                   93	        position = m_BoneMatrices[int(inHWBoneIndex.x)] * position;
                                   94	        tangent = m_BoneMatrices[int(inHWBoneIndex.x)] * tangent;
                                   95	        normal = (mat3(m_BoneMatrices[int(inHWBoneIndex.x)][0].xyz,
                                   96	                       m_BoneMatrices[int(inHWBoneIndex.x)][1].xyz,
                                   97	                       m_BoneMatrices[int(inHWBoneIndex.x)][2].xyz) * normal);
                                   98	#else
                                   99	        mat4 mat = mat4(0.0);
                                   100	        mat += m_BoneMatrices[int(inHWBoneIndex.x)] * inHWBoneWeight.x;
                                   101	        mat += m_BoneMatrices[int(inHWBoneIndex.y)] * inHWBoneWeight.y;
                                   102	        mat += m_BoneMatrices[int(inHWBoneIndex.z)] * inHWBoneWeight.z;
                                   103	        mat += m_BoneMatrices[int(inHWBoneIndex.w)] * inHWBoneWeight.w;
                                   104	        position = mat * position;
                                   105	
                                   106	        mat3 rotMat = mat3(mat[0].xyz, mat[1].xyz, mat[2].xyz);
                                   107	        tangent = rotMat * tangent;
                                   108	        normal = rot
E/com.jme3.app.AndroidHarness: SEVERE Exception thrown in Thread[GLThread 183,5,main]
com.jme3.renderer.RendererException: compile error in: ShaderSource[name=Common/MatDefs/Misc/Unshaded.vert, defines, type=Vertex, language=GLSL100]
                               ERROR: 0:158: '=' : global variable initializers must be constant expressions 

                               at com.jme3.renderer.opengl.GLRenderer.updateShaderSourceData(GLRenderer.java:1200)
                               at com.jme3.renderer.opengl.GLRenderer.updateShaderData(GLRenderer.java:1227)
                               at com.jme3.renderer.opengl.GLRenderer.setShader(GLRenderer.java:1291)
                               at com.jme3.material.logic.DefaultTechniqueDefLogic.render(DefaultTechniqueDefLogic.java:94)
                               at com.jme3.material.Technique.render(Technique.java:166)
                               at com.jme3.material.Material.render(Material.java:968)
                               at com.jme3.renderer.RenderManager.renderGeometry(RenderManager.java:616)
                               at com.jme3.renderer.queue.RenderQueue.renderGeometryList(RenderQueue.java:266)
                               at com.jme3.renderer.queue.RenderQueue.renderQueue(RenderQueue.java:305)
                               at com.jme3.renderer.RenderManager.renderViewPortQueues(RenderManager.java:870)
                               at com.jme3.renderer.RenderManager.flushQueue(RenderManager.java:781)
                               at com.jme3.renderer.RenderManager.renderViewPort(RenderManager.java:1097)
                               at com.jme3.renderer.RenderManager.render(RenderManager.java:1145)
                               at com.jme3.app.SimpleApplication.update(SimpleApplication.java:253)
                               at com.jme3.app.AndroidHarness.update(AndroidHarness.java:497)
                               at com.jme3.system.android.OGLESContext.onDrawFrame(OGLESContext.java:336)
                               at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1548)
                               at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1259)

Is a higher GLSL version required to work with InstanceNode?

mhhh that’s weird, is that really the whole log?
The error is thrown line 158 and the output contains only 108 lines.

Yes, that is the whole log. I read the source of Unshaded.vert, thought the error line may be in Instance.glsllib: 43.

Alright, the worldMatrix declaration needs to be moved in transformWorld.
I pushed a fix, but I can’'t test right now, could you test?

OK, I’ll try it later

I copied the worldMatrix into transformWorld, then I got:

java.lang.IllegalArgumentException: Expected receiver of type sun.nio.ch.DirectBuffer, but got java.nio.ByteBufferAsFloatBuffer

com.jme3.renderer.RendererException: Mesh instancing is not supported by the video hardware

E/com.jme3.util.BufferUtils: SEVERE {0}
                         java.lang.IllegalArgumentException: Expected receiver of type sun.nio.ch.DirectBuffer, but got java.nio.ByteBufferAsFloatBuffer
                             at java.lang.reflect.Method.invoke(Native Method)
                             at com.jme3.util.BufferUtils.destroyDirectBuffer(BufferUtils.java:1330)
                             at com.jme3.scene.instancing.InstancedGeometry.setMaxNumInstances(InstancedGeometry.java:196)
                             at com.jme3.scene.instancing.InstancedGeometry.addInstance(InstancedGeometry.java:322)
                             at com.jme3.scene.instancing.InstancedNode.addToInstancedGeometry(InstancedNode.java:239)
                             at com.jme3.scene.instancing.InstancedNode.instance(InstancedNode.java:293)
                             at com.jme3.scene.instancing.InstancedNode.instance(InstancedNode.java:300)
                             at com.jme3.scene.instancing.InstancedNode.instance(InstancedNode.java:306)
                             at net.jmecn.mygame.TestInstanceNode.simpleInitApp(TestInstanceNode.java:94)
                             at com.jme3.app.SimpleApplication.initialize(SimpleApplication.java:220)
                             at com.jme3.app.AndroidHarness.initialize(AndroidHarness.java:478)
                             at com.jme3.system.android.OGLESContext.onDrawFrame(OGLESContext.java:328)
                             at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1548)
                             at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1259)
E/com.jme3.app.AndroidHarness: SEVERE Exception thrown in Thread[GLThread 99,5,main]
                           com.jme3.renderer.RendererException: Mesh instancing is not supported by the video hardware
                               at com.jme3.renderer.opengl.GLRenderer.renderMesh(GLRenderer.java:2764)
                               at com.jme3.material.logic.DefaultTechniqueDefLogic.renderMeshFromGeometry(DefaultTechniqueDefLogic.java:69)
                               at com.jme3.material.logic.DefaultTechniqueDefLogic.render(DefaultTechniqueDefLogic.java:95)
                               at com.jme3.material.Technique.render(Technique.java:166)
                               at com.jme3.material.Material.render(Material.java:968)
                               at com.jme3.renderer.RenderManager.renderGeometry(RenderManager.java:616)
                               at com.jme3.renderer.queue.RenderQueue.renderGeometryList(RenderQueue.java:266)
                               at com.jme3.renderer.queue.RenderQueue.renderQueue(RenderQueue.java:305)
                               at com.jme3.renderer.RenderManager.renderViewPortQueues(RenderManager.java:870)
                               at com.jme3.renderer.RenderManager.flushQueue(RenderManager.java:781)
                               at com.jme3.renderer.RenderManager.renderViewPort(RenderManager.java:1097)
                               at com.jme3.renderer.RenderManager.render(RenderManager.java:1145)
                               at com.jme3.app.SimpleApplication.update(SimpleApplication.java:253)
                               at com.jme3.app.AndroidHarness.update(AndroidHarness.java:497)
                               at com.jme3.system.android.OGLESContext.onDrawFrame(OGLESContext.java:336)
                               at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1548)
                               at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1259)

I dont know if it has some problems with is code in com.jme3.util.ReflectionAllocator. This part of code was in BufferUtils (3.1.0-stable), some one moved it to ReflectionAllocator on master.

private static Method cleanerMethod = null;
private static Method cleanMethod = null;
private static Method viewedBufferMethod = null;
private static Method freeMethod = null;

static {
    // Oracle JRE / OpenJDK
    cleanerMethod = loadMethod("sun.nio.ch.DirectBuffer", "cleaner");
    cleanMethod = loadMethod("sun.misc.Cleaner", "clean");
    viewedBufferMethod = loadMethod("sun.nio.ch.DirectBuffer", "viewedBuffer");
    if (viewedBufferMethod == null) {
        // They changed the name in Java 7
        viewedBufferMethod = loadMethod("sun.nio.ch.DirectBuffer", "attachment");
    }

    // Apache Harmony (allocated directly, to not trigger allocator used
    // logic in BufferUtils)
    ByteBuffer bb = ByteBuffer.allocateDirect(1);
    Class<?> clazz = bb.getClass();
    try {
        freeMethod = clazz.getMethod("free");
    } catch (NoSuchMethodException ex) {
    } catch (SecurityException ex) {
    }
}

Well I guess this is the end of the story…
If the hardware doesn’t support instancing… well there not much you can do.