Fun with Bloom

I'm trying to get bloom working in a game I'm working on and I get pretty exception:


INFO: Render to Texture Pbuffer supported!
Aug 1, 2006 6:40:40 PM com.jme.renderer.lwjgl.LWJGLTextureRenderer initPbuffer
WARNING: LWJGL reports this card supports Render to Texture, but fails to enact it.  Please report this to the LWJGL team.
Aug 1, 2006 6:40:40 PM com.jme.renderer.lwjgl.LWJGLTextureRenderer initPbuffer
WARNING: Attempting to fall back to Copy Texture.
Aug 1, 2006 6:40:40 PM com.jme.renderer.lwjgl.LWJGLTextureRenderer initPbuffer
WARNING: Failed to create Pbuffer.
org.lwjgl.LWJGLException: Could not share contexts
   at org.lwjgl.opengl.WindowsContextImplementation.nCreate(Native Method)
   at org.lwjgl.opengl.WindowsContextImplementation.create(WindowsContextImplementation.java:48)
   at org.lwjgl.opengl.Context.<init>(Context.java:123)
   at org.lwjgl.opengl.Pbuffer.<init>(Pbuffer.java:194)
   at com.jme.renderer.lwjgl.LWJGLTextureRenderer.initPbuffer(LWJGLTextureRenderer.java:601)
   at com.jme.renderer.lwjgl.LWJGLTextureRenderer.initPbuffer(LWJGLTextureRenderer.java:615)
   at com.jme.renderer.lwjgl.LWJGLTextureRenderer.<init>(LWJGLTextureRenderer.java:167)
   at com.jme.renderer.lwjgl.LWJGLTextureRenderer.<init>(LWJGLTextureRenderer.java:111)
   at com.jme.system.lwjgl.LWJGLDisplaySystem.createTextureRenderer(LWJGLDisplaySystem.java:323)
   at com.jmex.effects.glsl.BloomRenderPass.<init>(BloomRenderPass.java:125)
   at com.captiveimagination.gb.state.SpaceGameState.initSpace(SpaceGameState.java:81)
   at com.captiveimagination.gb.state.SpaceGameState.init(SpaceGameState.java:47)
   at com.captiveimagination.gb.state.SpaceGameState.<init>(SpaceGameState.java:31)
   at com.captiveimagination.gb.state.SectorOne.<init>(SectorOne.java:22)
   at com.captiveimagination.gb.GalaxiesBeyondClient.<init>(GalaxiesBeyondClient.java:16)
   at com.captiveimagination.gb.GalaxiesBeyondClient.main(GalaxiesBeyondClient.java:22)
Exception in thread "main" java.lang.NullPointerException
   at com.jme.scene.state.lwjgl.LWJGLShaderObjectsState.isSupported(LWJGLShaderObjectsState.java:76)
   at com.jmex.effects.glsl.BloomRenderPass.<init>(BloomRenderPass.java:142)
   at com.captiveimagination.gb.state.SpaceGameState.initSpace(SpaceGameState.java:81)
   at com.captiveimagination.gb.state.SpaceGameState.init(SpaceGameState.java:47)
   at com.captiveimagination.gb.state.SpaceGameState.<init>(SpaceGameState.java:31)
   at com.captiveimagination.gb.state.SectorOne.<init>(SectorOne.java:22)
   at com.captiveimagination.gb.GalaxiesBeyondClient.<init>(GalaxiesBeyondClient.java:16)
   at com.captiveimagination.gb.GalaxiesBeyondClient.main(GalaxiesBeyondClient.java:22)



The relevent code:

        RenderPass rootPass = new RenderPass();
        rootPass.add(rootNode);
        game.getPassManager().add(rootPass);
       
        BloomRenderPass brp = new BloomRenderPass(game.getCamera(), 4);
        brp.add(rootNode);
        brp.setUseCurrentScene(true);
        game.getPassManager().add(brp);



Any ideas?  I'm not using SimplePassGame, but I've initialized the BasicPassManager in StandardGame (and if I can get this working I'll check it in).

Thanks

There's not a lot of info to work with, but my guess is the pbuffer is being constructed either in another thread than the opengl thread or it is being created when the display system is not completely setup.  I have not seen that particular issue myself though, so just a guess.  In any event, a small test class that recreates this exception would be helpful.

I can guarantee that it's in another thread. :)  I'm trying to be multithreaded. :wink:



Okay, so is there any way we can fix this to work in another thread or do I have to de-thread it?

All OpenGL activity must be in the same thread.  Other than that, multi-threading is possible with the normal threading caveats.



Creating a BloomRenderPass immediately creates a Pbuffer and loads a number of shaders.  Therefore, you need to do the actual creation of the pass in the render thread.  You may be able to look at where you are creating the display system and such and do it there.  Otherwise, you may want to delay the creation of the pass and do it inside your first render via the use of a RenderThreadExecutable and the RenderThreadActionQueue (or something similar).



So basically something close to:


BloomRenderPass brp = null;

protected void initPass() {
    RenderThreadExecutable exe = new RenderThreadExecutable() {
            public void doAction() {
               brp = new BloomRenderPass(game.getCamera(), 4);
               brp.add(rootNode);
               brp.setUseCurrentScene(true);
               game.getPassManager().add(brp);
            }
        };
        RenderThreadActionQueue.addToQueue(exe);
}



and in your game loop, often between the update and render commands:

RenderThreadActionQueue.processQueueItem();



Using the queue is useful because I guarentee you will run into another thread issue later. :)

I created my own feature alternative that makes things a little more 1.5ish. :slight_smile:


            Callable<BloomRenderPass> callable = new Callable<BloomRenderPass>() {
                public BloomRenderPass call() throws Exception {
                    return new BloomRenderPass(game.getCamera(), 4);
                }
            };
            Future<BloomRenderPass> future = game.update(callable);
            BloomRenderPass brp = future.get();
            brp.add(rootNode);
            brp.setUseCurrentScene(true);
            game.getPassManager().add(brp);



I checked the new feature into StandardGame, so you can simply create a Callable implementation that returns your object, and then get the Future back that will contain the object.  This seems a lot more capable way of doing things to me.  If you agree, what do you think about switching to this as a more standard way of doing things?  I checked the capability into StandardGame (Future<V> update(Callable<V>) and Future<V> render(Callable<V>) - that will execute in the respective update/render methods) if you're interested in looking at it closer.

This offers protection for timing out, exception handling, non-blocking, blocking, and complete thread-safety.

Interesting, although instead of reinventing jme functionality again, why not integrate your ideas into what is already there?

Happy to, but I first wanted to make sure you guys would be happy with the way the new system is.  I can start converting stuff over to the new system this weekend if you don't have any issue with it.

integrate into what parts of jme?



why is it called Future?

Right… we should stick to explanitive names like RenderThreadExecutable…

Hey, I didn’t come up with the names, I just used them. :-p



http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/Future.html

http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/Callable.html



I had sort of the same idea, except instead of not reinventing jme functionality I was actually deprecating jme functionality by using the features of 1.5. :wink:

I haven't looked at Future and Callable at all, in fact, today was the first time I've heard of it. So, first, I'll have to educate myself (gives me a blog entry :wink: ) and secondly give my opinion. I do have to say, I like anything that insures thread safety BUT threads scare the living crap out of me (which you know already, we've had this conversation before), so I hate putting anything in there that promotes their use. This could be an out of date attitude, I'm known to have a few of those.

Many people seem to echo the sentiment of fear of threading in games.  In a sense I do agree with that, but at the same time there can be much gained.  My fears lie in bad implementations of threading that end up being a nightmare to handle.  I believe threading can in fact make debugging easier in some cases (with a good tool like Eclipse that can pause one or all threads for debugging) when things are properly separated out.  However, the work here does not actually force multithreading.  Actually, the code that I just contributed that we're discussing simply lets you interject things for a single-threaded approach…so in a sense, it helps get closer to a single-threaded than enforcing multi-threading further.



I thought we had decided one of the next major goals was to make jME completely thread-safe?  I think features like this are a major stride in that direction.



Renanse, give me the go ahead and I'll start ripping out RenderThreadExecutable for ya. :wink:

i need to look into those packages as well before i say anything.

i'm all for making it thread safe offcourse, but i agree with mojo in many aspects…with dual processors, dual core etc that comes with pc's, playstations etc nowdays it's surely becoming more and more valuable to do threading…but still i don't know anyone that have been into making commercial game development for a few years(including myself) that doesnt get the big shiver when hearing about threading…



i'll make some more elaborate posts later tonight…

jME is already largely thread safe… in the sense that where want it to be, it is. (there might be a few places where it's not). You'll have to do your own synchronization though…



Now that there are many dual core processors, and even SMP is making a comeback (AMD's 4x4) so if you want to get the maximum from your hardware you'll have to use threads eventually. Thankfully using them with Java is a lot easier than with C/C++, which I think is where the sentiment against them comes from a bit.

I think the easy way to make a multithreaded game would be putting scenegraph processing, game logic, ai, physics etc. into a separate thread. That's possible with the current jME when you care for proper access to the scenegraph (either by synchronizaion or by queueing scenegraph calls). The only additional point here may be to load models and textures in background. Is this what you are trying to achieve, darkfrog?

But if we talk about scalability here and want to spread processing of a single large scenegraph amoungst processors, I expect it to get very tough (and probably risc to downgrade single processor performance).



Regarding the 'thread safety' of jME I have a different opinion than Llama: If some API is 'thread safe' it means you don't need to syncronize the calls to it from outside. So most parts of jME are not 'thread safe' (at least in my wording :)). It's not even really guarded against reentrance (e.g. update methods of controllers should not call remove from Node or controller list).

irrisor said:

I think the easy way to make a multithreaded game would be putting scenegraph processing, game logic, ai, physics etc. into a separate thread. That's possible with the current jME when you care for proper access to the scenegraph (either by synchronizaion or by queueing scenegraph calls). The only additional point here may be to load models and textures in background. Is this what you are trying to achieve, darkfrog?
But if we talk about scalability here and want to spread processing of a single large scenegraph amoungst processors, I expect it to get very tough (and probably risc to downgrade single processor performance).

Regarding the 'thread safety' of jME I have a different opinion than Llama: If some API is 'thread safe' it means you don't need to syncronize the calls to it from outside. So most parts of jME are not 'thread safe' (at least in my wording :)). It's not even really guarded against reentrance (e.g. update methods of controllers should not call remove from Node or controller list).


You shouldn't force one model of synchronization on people. That's why, IMHO, by your defination jME should never be thread safe. The reentrance issue is not a thread issue (it happens in single threaded mode too of course). If you're serious about a multithreaded game, you should carefully choose your own locking model that's suited best for that game. We could provide some tools though, maybe (eg. a "LockNode") that puts all actions for it's childeren in the same synchronized block.

A simpler way to speed up things, as I argued in another thread (no pun intended) is to split up tasks over 2 or more threads. jME still more or less (and quite logically so) depends on one "phase" completing before starting the next. It's tricky to have a thread process the scenegraph while other threads are changing coordinates, etc.

A good example of what you could split is updates, escp if you have lot's of animation, must recalculate bounding volumes, etc. You'll still have only 1 thread doing work during the "OpenGL" phase, though there's still other tasks for threads (background loading, for example).

Going back to the topic of using this change…



Personally, I just don't see a big reason to switch to something just because it's in 1.5.  Because Sun added something new does not necessarily mean it is suitable for our purposes.  For example, the new for loop syntax can make extra garbage and is unsuitable inside a tight loop IMHO.



Sometimes I feel we spend too much time dabbling with functionality that already works "ok" and very little time looking towards future new features for jME.  I think that's what you are hearing in my reactions to this.  That said, I like the two queues and the wrapper provided by GameTask.  It looks like something worth adapting although It's going to be hell to port at work because we do lots of render thread tasks in our editor.  :(  Actually, come to think of it, I wrapped much of that too, so I guess it will be only moderately painful. :wink:



Darkfrog, please promote your GameTag to its own class and DEPRECATE the RenderThreadExecutable and RenderThreadActionQueue classes.  Let's also extract the queue system from StandardGame to a reusable class. (So StandardGame would have two instances of that class, one for update and one for render.)  The queue class should be generic and simply have the execute method and an add method that takes a Callable.  When you've done that, let me implement the new way of doing things where it will now cry deprecated (resist the urge to do those yourself.)  Then we at least have two sets of eyes on this change.

Well, first of all, I disagree that imposing thread-safety in jME is a bad idea.  It makes more sense to be thread-safe in the API as a whole so as to reduce the headache for people doing the development with it.  A valid point was raised about imposing our own way of doing things though.  Previous to 1.5 I think that would be a valid enough point to leave things alone.  However, there are some amazing new features in 1.5 that allow us to provide “best-practice” thread-safety in jME without sacrificing and still remaining standardized.  I do agree with Renanse that being 1.5 compliant just for the sake of 1.5 compliance is a bad idea.  However, I think that all the threading support they’ve added is far superior to anything we could come up with on our own without creating our own native libraries.



Synchronization is not necessarily the answer for thread-safety anymore either.  Take a look at Lock, all the Concurrent classes, and the atomic objects that have been introduced.  All of this combine to allow simlultaneous calls when reasonable and synchronized calls when necessary.  I just recently learned about all the new features of 1.5 for threading and had to implement it all into JGN, so I’ve got a good grasp on it now and I would encourage everyone else to look into it as well as I think jME could really benefit from it.  I found Sun’s threading tutorial very useful for this:



http://java.sun.com/docs/books/tutorial/essential/concurrency/index.html



However, it looks as if they’ve started changing it over to 1.6 within the past day…



Renanse, I’ll try to accomplish all of those tasks today.  I’m glad that value is seen in this.



Thanks guys.

On a side-note…I would like to discuss events and listeners at some point.  I think there could be definite value in the optional utilization of event handling.  The main reason this came up to me was I've been thinking about the sound system in jME.  I believe that if we had a nice event system that we could simply create SoundEvents that trigger on certain events (such as the collision between objects) and it would simplify and objectify things so much better than what we've got now.  I think it can be done in such a way that we can keep from having a noticable performance hit.

Okay, the changes are checked into CVS. The new classes are as follows:

com.jme.util.GameTaskQueue
com.jme.util.GameTask


I made GameTask only visible in that package since it should never be used directly by anything but GameTaskQueue.  Everything else will simply create Callables and receive Futures (even though they are instances of GameTasks).

If you guys are entirely on-board with this what do you think about converting other functionality like JMEAction to utilize these features as well?