Java-Gaming.org    
Featured games (79)
games approved by the League of Dukes
Games in Showcase (476)
Games in Android Showcase (106)
games submitted by our members
Games in WIP (533)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  LWJGL Graphics in seperate thread?  (Read 5469 times)
0 Members and 1 Guest are viewing this topic.
Offline Ciaran54

Junior Member


Medals: 4



« Posted 2011-12-30 20:40:16 »

Hi, Java-gaming!

A friend and I are programming a game together in java, and I wrote a new graphics engine specifically for the game, using LWJGL. However, my friend believes that the game would be both better structured and with better performance if all of the drawing occurred in a separate thread. All of the objects to be drawn are contained within a huge tile map. His solution to keep everything thread safe and synchronised well is to make a deep copy of the map to be drawn, and then (in a thread safe way) move the area across to the graphics thread to be drawn. We already have some aspects, such as pathfinding, multithreaded, but he seems determined to do drawing in a separate thread... I just get this gut instinct that it is a bad idea because it goes against the standard game loop...

Am I being narrow minded? or is it it usually more sensible to keep drawing in the same thread as the game loop?

Thank you Wink


(I wasn't sure whether to post this in the 2d or performance forum, hope this was the right choice)
Online princec

JGO Kernel


Medals: 342
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #1 - Posted 2011-12-30 20:48:02 »

This does work but.... it is very difficult to get working, and in my various tests, rarely achieves more than about 10-20% frame rate increase. And then only if you've got a dual-core system: you'll then find that the performance is slightly worse on a single-core system, which last time I looked was still about 25% of the systems out there in the wild. I'd say don't bother doing it if I were you and concentrate on getting it working single-threaded.

Cas Smiley

Offline theagentd
« Reply #2 - Posted 2011-12-31 00:08:51 »

Nice to see people realize that a computer has more than one core!

The main problem with threading out graphics is that you have to make all OpenGL calls from the same thread, meaning that the graphics thread has to own the OpenGL context. This makes it a little difficult to initialize OpenGL (the Display, e.t.c.) and load textures and shaders, since they also have to be in the same thread. It's much easier to flip it around and thread out logic instead, since you can call OpenGL commands from the main thread in that case.

There are 2 kinds of thread-safe: Either you add synchronization to a normal solution, or you adapt the solution to not need synchronization in the first place. The second one usually has slightly worse single-core performance, but scales MUCH better with multiple cores, since synchronization costs some performance. Separating graphics and logic is pretty easy, but getting it perfect is pretty hard. The logic thread will read and write, e.g. update the game state, while the rendering will ONLY read information to draw stuff. Not much synchronization should be needed, but there is a big problem: The state may change during drawing, which may surprise the rendering thread. Some objects may have data from the last update while some objects have been updated. This is okay for a relatively simple 2D game, but in 3D, this can produce seams in the world!

I made a small library for threading games. In it you're meant to setup Task objects which perform different tasks. A Task has a list of other Tasks that needs to have been completed before it's allowed to be run. The Tasks are compiled into a TaskTree which can be run from a GameExecutor. This allows pretty complex threading to be very easily implemented.
 - You can make two Tasks run at the same time by having two Tasks that do not require each other. A multithreaded GameExecutor will put these on different threads. You're not supposed to have any manual synchronization inside Tasks.
 - You can also make Tasks themselves multi-threaded by using a SplitTask. For example this allows you to multithread movement updating by updating every other object from two different threads.

You can take a look on it here: http://code.google.com/p/small-java-threading-library/. Sadly, the interest on this forum was lower than I expected for it (0 downloads so far >_>).

Myomyomyo.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline ra4king

JGO Kernel


Medals: 336
Projects: 2
Exp: 5 years


I'm the King!


« Reply #3 - Posted 2011-12-31 04:20:32 »

How about best of both worlds (pseudocode):
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
//main thread:
public void gameLoop() {
    boolean isLogicThreadRunning = false;
   
    if(Runtime.getRuntime().availableProcessors() > 1) {
        new LogicThread().start(); //the LogicThread just calls update in a loop
       isLogicThreadRunning = true;
    }
   
    while(isGameRunning) {
        if(!isLogicThreadRunning)
            update();
       
        render();
    }
}

Then just synchronize as necessary Grin

You can take a look on it here: http://code.google.com/p/small-java-threading-library/. Sadly, the interest on this forum was lower than I expected for it (0 downloads so far >_>).
I don't remember ever seeing this before, did you make a thread about it?

Offline sproingie

JGO Kernel


Medals: 201



« Reply #4 - Posted 2011-12-31 04:50:34 »

I don't remember ever seeing this before, did you make a thread about it?

 Pointing I see what you did there  Grin
Offline ra4king

JGO Kernel


Medals: 336
Projects: 2
Exp: 5 years


I'm the King!


« Reply #5 - Posted 2011-12-31 07:05:47 »

Teehee Grin

Offline delt0r

JGO Knight


Medals: 26
Exp: 18 years


Computers can do that?


« Reply #6 - Posted 2011-12-31 11:03:31 »

My engine is multithreaded. I have a game engine thread, the rendering thread and the network threads. For a game that has AI there is the AI threads.

My reason for doing was to separate the screen frame rate from the game turn rate. Turns out that it kinda doesn't work well without a lot of interpolation code on the rendering side. However this still makes the code much cleaner. Most of the work is still rendering so there is not really a performance increase on a mutlicore system in this case.

For synchronization, the engine gives out game state snapshots to the renderer with a thread safe queue from java.util.concurrent. The controller (aka gui in the renderer) sends command objects to the engine which again just uses a thread safe queue. The map, since it does not change, is shared without any synchronization.

Keeping all the opengl code in a single thread was easy enough. You can always use Display.makeCurrent() otherwise.

I find thread programing reasonably easy if you keep the threads coarse and the communication between them simple. Note also that opengl drivers may do things in the background for you too.

But princec does have a point... get it working first... get it playable.

I have no special talents. I am only passionately curious.--Albert Einstein
Offline theagentd
« Reply #7 - Posted 2011-12-31 11:44:29 »

I don't remember ever seeing this before, did you make a thread about it?

 Pointing I see what you did there  Grin
Bwahahahaha! Made me laugh out loud! And yes, I did... http://www.java-gaming.org/topics/small-java-threading-library/25143/view.html Like I said, it kind of went under the radar...


Threading should be one of the last things you implement in the game, but you should still be coding with concurrency in mind if you plan on implementing it later. I am making a strategy game, which means that the CPU is a huge bottleneck in AI, line of sight, e.t.c, meaning that threading is pretty much necessary for large maps with many units. I expect an almost linear increase in performance for the parts I plan to multithread using the threading library I made.

Myomyomyo.
Offline Ciaran54

Junior Member


Medals: 4



« Reply #8 - Posted 2011-12-31 12:38:28 »

Wow, thanks everyone for the huge response Cheesy

This does work but.... it is very difficult to get working, and in my various tests, rarely achieves more than about 10-20% frame rate increase. And then only if you've got a dual-core system: you'll then find that the performance is slightly worse on a single-core system, which last time I looked was still about 25% of the systems out there in the wild. I'd say don't bother doing it if I were you and concentrate on getting it working single-threaded.

Cas Smiley

Thanks for the info, I think i will follow this advice. Wink


Nice to see people realize that a computer has more than one core!

The main problem with threading out graphics is that you have to make all OpenGL calls from the same thread, meaning that the graphics thread has to own the OpenGL context. This makes it a little difficult to initialize OpenGL (the Display, e.t.c.) and load textures and shaders, since they also have to be in the same thread. It's much easier to flip it around and thread out logic instead, since you can call OpenGL commands from the main thread in that case.

There are 2 kinds of thread-safe: Either you add synchronization to a normal solution, or you adapt the solution to not need synchronization in the first place. The second one usually has slightly worse single-core performance, but scales MUCH better with multiple cores, since synchronization costs some performance. Separating graphics and logic is pretty easy, but getting it perfect is pretty hard. The logic thread will read and write, e.g. update the game state, while the rendering will ONLY read information to draw stuff. Not much synchronization should be needed, but there is a big problem: The state may change during drawing, which may surprise the rendering thread. Some objects may have data from the last update while some objects have been updated. This is okay for a relatively simple 2D game, but in 3D, this can produce seams in the world!

I made a small library for threading games. In it you're meant to setup Task objects which perform different tasks. A Task has a list of other Tasks that needs to have been completed before it's allowed to be run. The Tasks are compiled into a TaskTree which can be run from a GameExecutor. This allows pretty complex threading to be very easily implemented.
 - You can make two Tasks run at the same time by having two Tasks that do not require each other. A multithreaded GameExecutor will put these on different threads. You're not supposed to have any manual synchronization inside Tasks.
 - You can also make Tasks themselves multi-threaded by using a SplitTask. For example this allows you to multithread movement updating by updating every other object from two different threads.

You can take a look on it here: http://code.google.com/p/small-java-threading-library/. Sadly, the interest on this forum was lower than I expected for it (0 downloads so far >_>).

Thanks for the info, I'll take a look at that threading example you made Wink
(although we have already implemented a lot of threading, so I will only read it for advice, thanks anyway Wink)

How about best of both worlds (pseudocode):
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
//main thread:
public void gameLoop() {
    boolean isLogicThreadRunning = false;
   
    if(Runtime.getRuntime().availableProcessors() > 1) {
        new LogicThread().start(); //the LogicThread just calls update in a loop
       isLogicThreadRunning = true;
    }
   
    while(isGameRunning) {
        if(!isLogicThreadRunning)
            update();
       
        render();
    }
}

Then just synchronize as necessary Grin

Yeah, I think we'll persue this route, thanks Wink


My engine is multithreaded. I have a game engine thread, the rendering thread and the network threads. For a game that has AI there is the AI threads.

My reason for doing was to separate the screen frame rate from the game turn rate. Turns out that it kinda doesn't work well without a lot of interpolation code on the rendering side. However this still makes the code much cleaner. Most of the work is still rendering so there is not really a performance increase on a mutlicore system in this case.

For synchronization, the engine gives out game state snapshots to the renderer with a thread safe queue from java.util.concurrent. The controller (aka gui in the renderer) sends command objects to the engine which again just uses a thread safe queue. The map, since it does not change, is shared without any synchronization.

Keeping all the opengl code in a single thread was easy enough. You can always use Display.makeCurrent() otherwise.

I find thread programing reasonably easy if you keep the threads coarse and the communication between them simple. Note also that opengl drivers may do things in the background for you too.

I'm not sure using interpolation would be very effective for our game, there is a lot of movement going on, and it's tile based, so I think it would be fairly obvious if a character overshot and had to jerk back in another direction...

Threading should be one of the last things you implement in the game, but you should still be coding with concurrency in mind if you plan on implementing it later. I am making a strategy game, which means that the CPU is a huge bottleneck in AI, line of sight, e.t.c, meaning that threading is pretty much necessary for large maps with many units. I expect an almost linear increase in performance for the parts I plan to multithread using the threading library I made.

We are making a strategy game also, but I feel it is always easier to multithread code while you know it well. If you code it thinking of concurrency anyway, then usually it won't take long to actually make it concurrent, I feel it is more useful to make it concurrent at the time of writing, really.

--------------

Once again, thank you all very much for all of the assistance Wink

Offline delt0r

JGO Knight


Medals: 26
Exp: 18 years


Computers can do that?


« Reply #9 - Posted 2011-12-31 13:11:46 »

My point was not clear about interpolation. It was a royal PITA and i dropped it. I need the engine to run as fast or faster than the frame rate for now. Getting interpolation to work is not as easy as it looks.

I have no special talents. I am only passionately curious.--Albert Einstein
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Orangy Tang

JGO Kernel


Medals: 56
Projects: 11


Monkey for a head


« Reply #10 - Posted 2011-12-31 13:43:07 »

For synchronization, the engine gives out game state snapshots to the renderer with a thread safe queue from java.util.concurrent.

This is the problem I always have when thinking about decoupling logic and rendering. To not get hideous threading issues you need to take either one interpolation-aware snapshot, or two snapshots and somehow interpolate between them. Now maybe other people's games are different but even with a very simple game you could have hundreds of different entities, items, etc. all moving around with position/velocity/angle. Now *every* single game logic class has to be interpolation-aware, adding extra tedium and work when writing any gameplay code.

It seems like the response is often 'just clone the world state and interpolate' as if that's the easiest thing in the world (not trying to pick on delt0r here, since he said it was a massive PITA). Not to mention that cloning the world is decidedly non-trivial in terms of cpu and memory usage.

I have *never* seen a non-trivial game doing the clone-and-interpolate method, certainly never in a console game where the memory usage would be prohibitive. Everything I've seen takes a more pragmatic view by running (say) animation at a lower interval (like at 10fps instead of 60fps) or possibly offloading the heavy computation to a thread (ai) but from the purposes of the game loop it still looks like it's being updated and rendering at full rate.

Would love to hear from someone who's done a non-trivial game with the clone-and-interpolate method, and how they solved the above problems.

[ TriangularPixels.com - Play Growth Spurt, Rescue Squad and Snowman Village ] [ Rebirth - game resource library ]
Offline delt0r

JGO Knight


Medals: 26
Exp: 18 years


Computers can do that?


« Reply #11 - Posted 2011-12-31 14:01:40 »

I don't interpolate. I just use the latest snapshot. If they are fast enough it works fine.

However i did manage to get interpolation working. I will put it back in too later if needed. The main reason i wanted it was because i didn't want 60 network "frames" per second. But jittery networks are a way of life, so i wanted to not just interpolate, but adaptively with changing update rate in a way that doesn't look bad. The trick was to always be 2 frames behind the game engine, that is i can interpolate between frame n to n+1, and i adaptively change the speed so that by the time i get to frame n+1 the n+2 frame is available. I even used a PID controller to do it, well i drooped the P.

This however adds quite a bit of lag. By the time the frame rate is fast enough to get the lag down, it was fast enough to not bother with interpolation. So i just cut it out. If i need to add it later because of networking, i will add it at the engine level, not the view level. This keeps it all in one place.

And i am derailing another thread  persecutioncomplex

I have no special talents. I am only passionately curious.--Albert Einstein
Offline theagentd
« Reply #12 - Posted 2011-12-31 18:02:41 »

You don't have to interpolate everything. Just interpolating position/movement is pretty much enough for the game to look smooth. If you want more interpolation, just add it as you go. It's not that hard to integrate, just tedious.

Myomyomyo.
Offline Ciaran54

Junior Member


Medals: 4



« Reply #13 - Posted 2012-01-05 13:42:29 »

And i am derailing another thread  persecutioncomplex

Actually, Your story caused the discussion that fully answered my question, thanks Wink
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

pw (22 views)
2014-07-24 01:59:36

Riven (20 views)
2014-07-23 21:16:32

Riven (17 views)
2014-07-23 21:07:15

Riven (20 views)
2014-07-23 20:56:16

ctomni231 (48 views)
2014-07-18 06:55:21

Zero Volt (44 views)
2014-07-17 23:47:54

danieldean (35 views)
2014-07-17 23:41:23

MustardPeter (38 views)
2014-07-16 23:30:00

Cero (53 views)
2014-07-16 00:42:17

Riven (52 views)
2014-07-14 18:02:53
HotSpot Options
by dleskov
2014-07-08 03:59:08

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:58:24

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:47:22

How do I start Java Game Development?
by ra4king
2014-05-17 11:13:37

HotSpot Options
by Roquen
2014-05-15 09:59:54

HotSpot Options
by Roquen
2014-05-06 15:03:10

Escape Analysis
by Roquen
2014-04-29 22:16:43

Experimental Toys
by Roquen
2014-04-28 13:24:22
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!