Treading in Threading. ;)

The game I've been working on has been entirely focused towards everything outside the main OGL thread and it has come up with a few issues that I think could benefit from some re-working so they don't require to be run within the OGL thread:


  • Creating and attaching a new CameraNode apparently dies if it's instantiated and added outside of the OGL thread

  • BloomRenderPass - I've already mentioned this one, but thought it should be on the list

  • Any lock() methods also throw a fit if they're run outside of the OGL thread


This was just a quick list of the things I've come across thus far, I'll probably add more as I go.  This is a great experience as far as finding the places in jME that force you to be in the OpenGL thread.

When I was making my editor textures where the big problem with multitasking. Are there any problems with them now?

Anything that uses (practically) any kind of LWJGL method…



Hm… you'd think it'd be easy to debug this somehow. Is there an IDE where you can put a package wide breakpoint for a specific thread? (or even all threads but a specif one). I think the java debugging protocol would support this…



In any case you make a callee hierachy, and visually inspect it a bit for lwjgl methods, if you have any doubts.



Not sure what you mean with CameraNode. You should ideally synchronize all your additions to the scenegraph to happen when the Node you're adding to isn't being rendered (and you have to for removals). Look inside CameraNode, and you'll see it does nothing specific to any thread context, except in it's updateWorldData method.

Some of these things could be instantiated lazily, like bloom.  Textures may still have an issue since the manager needs access to OpenGL to determine if S3TC compression is available…  Although, those are static variables that should already have been instantiated for the default states by then.



Not sure about why lock would be an issue, maybe you are overlooking something?



You're not calling updateGeometricState after adding the cameranode, are you?

The CameraNode issue was actually the most difficult to figure out because it didn't actually throw an exception when I created and added it, but rather it threw some OpenGL issue with the camera update.  I sent it to the OGL thread and it worked just fine.  I can post a stacktrace of the issue tonight if it is helpful.



Renanse, yeah, I am calling updateGeometricState



Badmi, I haven't had any issues with textures at all.  I think some friendly developer fixed those issues a while back.

updateGeometricState would call updateWorldData on the CameraNode which applies a camera frame change.  So that would be a problem if called outside the OpenGL thread.

Oops, sorry, I misunderstood the question.  No, I'm not calling updateGeometricState outside of the OpenGL thread.  The only thing I'm doing is instantiating a CameraNode and adding it to my Node in my scene after the game update loop is already running.  It causes the OpenGL thread to throw the exception out.

And you're sure this exception is an OpenGL exception, not one from incorrect concurrent modification of a Node or something?

It could be due concurrent modification, but I'm not getting a concurrent modification exception.  :?



It was a GL something exception.

You wouldn't get one (those are thrown by iterators)…like I said, it's removing that'll get you in trouble as far as I know.



Look yourself what (Camera)Node does in it's constructor (hint: nothing but set a few fields). I'm clueless what could cause an OpenGL error from that. I'd think you do something with the Camera itself then, but I think you would have mentioned that.

It should be relatively easy to create a simple test yourself. :o  I won't be able to touch it until this evening.

Exception in thread "main" java.lang.NullPointerException
   at org.lwjgl.opengl.GL11.glMatrixMode(GL11.java:1737)
   at com.jme.renderer.lwjgl.LWJGLCamera.onFrameChange(LWJGLCamera.java:174)
   at com.jme.renderer.AbstractCamera.setFrame(AbstractCamera.java:602)
   at com.jme.scene.CameraNode.updateWorldData(CameraNode.java:110)
   at com.jme.scene.Spatial.updateGeometricState(Spatial.java:313)
   at com.jme.scene.Node.updateWorldData(Node.java:399)
   at com.jme.scene.Spatial.updateGeometricState(Spatial.java:313)
   at com.jme.scene.Node.updateWorldData(Node.java:399)
   at com.jme.scene.Spatial.updateGeometricState(Spatial.java:313)
   at com.captiveimagination.gb.state.SpaceGameState.init(SpaceGameState.java:63)
   at com.captiveimagination.gb.state.SpaceGameState.<init>(SpaceGameState.java:33)
   at com.captiveimagination.gb.state.SectorOne.<init>(SectorOne.java:32)
   at com.captiveimagination.gb.GalaxiesBeyondClient.<init>(GalaxiesBeyondClient.java:18)
   at com.captiveimagination.gb.GalaxiesBeyondClient.main(GalaxiesBeyondClient.java:24)



There's the stack trace I've been promising.  It occurs with this code when run outside the OGL thread:

                CameraNode cameraNode = new CameraNode("CameraNode", game.getCamera());
                ship.attachChild(cameraNode);



If I change it to:

        GameTaskQueueManager.getManager().update(new Callable<Object>() {
            public Object call() throws Exception {
                CameraNode cameraNode = new CameraNode("CameraNode", game.getCamera());
                ship.attachChild(cameraNode);
                return null;
            }
        });



Then all is happy-worky. ;)

Well, you can see for yourself in that stack trace that updateGeometricState is being called and the update to the cameranode is where it is dying.  Your SpaceGameState init method must be calling updateGeometricState on the scenegraph that cameranode was added to but not doing so in the opengl thread.

Oh…I think you're right.  So it wasn't throwing an exception before because the call to updateGeometricState wasn't really needing to do anything, but now that I'm updating the cameranode it has to do something and fails because it's not in the OpenGL thread?

Updating the camera node world data, updates the camera (which is done with LWJGL).