I'm currently working on a multi-threading safe rendering system and I would like to know your thoughts on how to correctly update the next step in the game world while the previous scene is currently rendering. Currently I am using LWJGL Opengl Bindings with Java. Here is pseudocode for my game loop as it is currently set up (which is probably just a basic loop that most people are familiar with):
//DrawingLayers are wrappers for in game entities and has an update
//and render method
game-loop:
addInputEventsToInputStack()
removeCompletedDrawingLayers()
foreach layer in DrawingLayerQueue :
layer.update(deltaTime) //update position/color/size for entity
layer.render() //performs OpenGL calls
if(layer.isCompleted):
addToCompletedDrawingLayersList()
swapBuffers() //blocks until scene is fully rendered
goto game-loop
My problem lies in the swapBuffers() method as it blocks until the scene is rendered which means I cannot perform any updates while that is going on. My thought on how to get around this is to:
Have a copy of all DrawingLayers that I use for updating the state of the entities and have the other copy as a reference for the rendering thread. And while a frame is rendering, kick off a thread just before swapBuffers() to update the copy that is not in use.
I'm wary of this approach as I believe creating the copies before every frame would slow the system down more than I would like.
Does my approach make sense, and if not, do you guys have any recommendations for how to do this? I'm open to a complete restructuring.
Updated: Based on datenwolf's suggestion I've changed my gameloop to the following:
//DrawingLayers are wrappers for in game entities and has an update
//and render method
//A future for the pre-processing task
Future preProcess = null
game-loop:
//Update: checks if we have a preprocessed update to wait for
//and waits for it to complete
if(preProcess != null):
preProcess.get()
preProcess = null
addInputEventsToInputStack()
removeCompletedDrawingLayers()
foreach layer in DrawingLayerQueue :
layer.render() //performs OpenGL calls
if(layer.isCompleted):
addToCompletedDrawingLayersList()
//UPDATE: the following just calls all the update methods for the layers
// in a new thread
preProcess = executorService.submit(new UpdateRunnable())
swapBuffers() //blocks until scene is fully rendered
goto game-loop
So far with this I've got a significant improvement in performance. There may be some race condition issues that I cant see, but overall Im happy with this improvement.
in the swapBuffers() method as it blocks until the scene is rendered
The blocking of the buffer swap is only partial by finishing the rendering. It usually also blocks due to wait for the retrace. However OpenGL guarantees you, that after any drawing command returns, the buffers accessed by it can be safely modified without any pending rendering operations being impaired. The implementation is required to make copies or copy-on-write mappings to all data.
Or in short terms: Just modify the data in the buffers. As soon as drawing calls (glDrawArrays, glDrawElements) return it's safe to do so.
Related
In short I was wondering, if I call JFrame.pack() on a frame that is already sized, will it take a long time to analyse this or will it simply return immediately? I ask for efficiency reasons. There is a picture in my frame that is being updated many times a second within a loop. Now JFrame.pack() has to be called after at least the first picture is drawn to insure that the frame is the right size.
To handle this what I have (in pseudo code) is:
boolean flag = false
while (condition) {
getNextPicture();
updateFrameWithPicture()
if (!flag) {
frame.pack()
flag = true;
}
}
Now I was wondering if there would be a problem if I just left out the check for the flag and always called frame.pack(). Could the program decide fast enough if the frame is already the correct size?
Tricky to estimate differences in performance as I am displaying images received on an RTP socket.
You are micro optimizing your code. Getting external data through a socket will always be slower than repainting a frame.
I am actually using a swing timer
You should NOT use the Timer to do the actual reading of the image on the socket. The GUI will block while the image is being read. You should be using a separate Thread to read the image. It will probably be better for you to use a SwingWorker and then publish() the images as they become available. Read the section from the Swing tutorial on Concurrency for more information.
just thought it would be easier to describe my question in terms of a while loop.
No, it is better to give the actual code as you can see your current code is incorrect. Don't make use guess what you are doing.
I'm working on an LWJGL game in which the world changes quite often, and because it's rather large, it causes the game to freeze for a fraction of a second every time the world and consequently the corresponding VBO is updated. I've reduced the time the game freezes for by moving all logic to a separate thread (well, it's actually the rendering code that's in a separate thread), but pushing the data to the graphics card still seems to create a noticeable delay. Is it possible to send that VBO in my logic thread so as not to slow down the game?
Additionally, if this belongs on gamedev.so, let me know so I can move it. I wasn't quite sure, so I decided to post here.
You can't use multitasking for rendering using OpenGL. Apparently I was wrong, though the rest of the answer is still great, if you want to fix the problem using only a single OpenGL Context.
Though I came across the same problem when I made an Infinite Procedural Terrain Generator, the problem was the same as your problem, each time the world updated or generated a new Terrain Chunk it would freeze for just a fraction of a second.
How to fix this
Basically how I fixed this was by doing the following.
Create a Thread Pool/Thread Queue, the each time the world changes, you let a separate Thread process/update or recreate the FloatBuffer (or which other buffer you use). Since usually that is the reason for the freezing, simply because it takes a lot of time to create the buffers, input and change all the data etc.
Here is a layout of what I mean.
class VBOAntiFreeze {
FloatBuffer vertex_data;
// Just add the rest of the FloatBuffers you use as well, like FloatBuffer
// normal_data; FloatBuffer color_data; etc.
// You would also have all the other variables as the vbo_handle, vertices count, etc.
boolean fresh = true;
boolean dirty, updating;
public void updateVBO() {
if (fresh && !updating) {
updating = true;
// You could execute new Threads by creating a
// Thread Pool/Thread Queue, that way, you will
// have some more control over all the threads.
new Thread(new Runnable() {
public void run() {
// Update and process all the FloatBuffers here!
dirty = true;
fresh = false;
updating = false;
}
}).start();
}
}
public void renderVBO() {
if (updating) {
return;
}
else if (fresh) {
updateVBO();
return;
}
if (dirty) {
// Buffer all the newly updated data
}
// Render the VBO here
}
}
By using this idea you probably won't be experiencing the random freezing, unless your VBO are insanely huge, thereby the if (dirty) buffer new data will/can probably still freeze a little, though I've never experienced that before. But just saying, to inform you!
I decided to write my comment up as an answer because it differs slightly from the other two answers in the overhead on the drawing thread. Instead of stalling the pipeline when you upload your vertex data or unmap your buffer, I propose double-buffering and exchanging the VBO used for drawing with the one used for submitting data after your worker thread finishes its update.
You will need two render contexts for this approach, each of which shares resources.
In your worker thread, you can allocate/stream subdata into a VBO like you normally would in your current approach, the only difference is you will be doing this to a VBO that is not used for drawing. When you complete filling this VBO with data, let your drawing thread know and then exchange the VBO used for drawing with the VBO used for streaming vertex data when it comes time to draw. Your worker thread should block until the drawing thread swaps VBOs in this scenario.
This way, instead of stalling your drawing thread when new data has to be submitted to the GPU, you will instead stall the thread used to stream new data until the drawing thread swaps VBOs. As a result rendering will be smooth(er), but updates may occur at more variable frequency. This is generally a desirable characteristic in interactive software like games - an extra frame of latency before something new pops up is often better than a frame that takes twice as long to finish.
If you want to queue up more than one update at a time, so that your update thread does not have to block as often, I would suggest implementing a circular buffer like derhass mentioned in his answer. But it sounds like you only need a front/back buffer from your problem description.
In general, a GL context can be current to a single thread at any time, and a thread can have one current GL context at any time. If you want to do parallel updates of GL objects, you have two options:
Use shared contexts. That way, each trhead can have its own GL context, but the objects like buffers textures, ... can be used (and modified) by both threads.
For your particular scenario. it might be enough to use (maybe a ring buffer of) mapped VBOs. You need the GL context only to map/unmap the buffer, but while it is mapped, you can access it in arbitrary threads - which don't need a GL context at all. Usually, a ring buffer of VBOs is used in such a scenario to avoid excessive synchronisation between the threads.
I have a java application that streams raw data and draws real time plots accordingly. this is handled by calling methods from a class i wrote that uses the Graphics object. i implemented algorithms in an overridden paintComponent method to generate all the plots from the most recent data. i have other methods in my class to update variables used in the paintComponent method to draw the graphs.
in my main class, i update my graphs periodically in a timer event handler. in the event handler i call methods from my graphs class that update certain variables, do a few calculations, and then call repaint() (which apparently is the correct way to call the paintComponent method).
my problem is, the algorithms i use in the paintComponent method can take a (relatively) long time to complete depending on the amount and resolution of my plots. (i haven't exactly run into this problem yet, but i'm trying to address it now). of course i wouldn't want all this graphing to hog all the processing time of my application, so i was wondering if it's possible to have "paintComponent" execute in a separate thread.
what would happen if i created a subclass in my main to run in a separate thread and simply called the graph methods i described? would that automatically make all of those methods (including paintComponent) execute in the new thread? or would i have to modify my graph class itself for this to work? ideally i would like to avoid modifying my graphs class because i have already designed it to work within the NetBeans GUI builder as a JPanel, and i'd like to avoid breaking that functionality.
There's a couple options.
One method is to use two BufferedImages, where you draw on one in separate thread, and paint from the other one, and switch as drawing completes (for what I assume is a snapshot every so often.)
A much better solution is to have a model of directly renderable data (as in the data it holds can be drawn without performing any further algorithmic work on it).
This means you will perform your alogirthms on a separate thread, calculate the values that will be used to paint, call SwingUtilities.invokeLater to update the model. The model will then only get updated on the Swing thread, and when you repaint, you have access to exactly the data you need to draw (and no extraneous data).
If this data is still so much that painting takes a long time (ie: if you're drawing charts with tons of data points), you'll send to calculate which parts of your window need repainting and fire repaint() on just that. This piece should be a lat resort however. 99% of your performance will come from moving the algorithms into a separate thread, and giving the painter access to directly renderable data.
If you look at best practices on updating a TableModel with external data, what you have is the work that gets the data occurring in a background thread (typically SwingWorker) and then posted to the actual model via invokeLater() (This is so the data doesn't get modified while your paint() is trying to read it.) and then firing appropriate events from within the model update that tell the table what cells changed. The table then knows what part of its viewport needs repainting and fires the appropriate repaint() method. During this time the background thread can continue retrieving data and adding new updates to the event queue via invokeLater.
you have to redirect paint methods to the SwingWorker or Runnable#Thread (all output to the GUI must be wrapped into invokeLater), example here or here
Well, if you want to improve the responsiveness of the GUI you could do the lengthy work in a SwingWorker, although I don't know that doing so will speed up your application any more.
I have a java application that streams raw data and draws real time
plots accordingly. this is handled by calling methods from a class i
wrote that uses the Graphics object.
To complete other's answer:
you should really consider to use JFreeChart. It's a good library for drawing charts and you can modify dynamically the displayed dataset (and do a lot of more things).
In the past I have used PCS to update Swing elements that displayed certain fields and everything worked as expected. However, I am now facing a relatively complex (in other words, terribly designed) UI that displays a lot of fields. Data updates come in bunches (a network packet containing new values for about 1,000 fields), and I was wondering what the proper way to handle something like this is.
My main concern is that whenever a data packet comes, 1,000 PropertyChangeEvents are triggered, causing 1,000 .repaint()'s (or .revalidate()'s or whatever). The more prudent way seemed to do something like "gui.stopRepainting(); fireAllThePropertyEvents(); gui.restartPainting();". Is there a way to do that, or is there maybe a better way to handle this ?
A repaint request is passed to the RepaintManager which in turn combines multiple requests into a single repaint.
I find it strange that you have 1000, fields of a single form. Assuming this in fact true then I doubt all 1000 will be visible at the same time. I believe the RepaintManager will only paint those that are visible so the overhead may not be as bad as you think.
I don't know of any way to stop the repaint, but maybe you could make the pane invisble, do the updates and then make it visible again.
Or maybe you can create a custom RepaintManager the does nothing. You instal it, do your updates and then reinstal the default manager.
I'm developing a real time strategy game clone on the Java platform and I have some conceptional questions about where to put and how to manage the game state. The game uses Swing/Java2D as rendering. In the current development phase, no simulation and no AI is present and only the user is able to change the state of the game (for example, build/demolish a building, add-remove production lines, assemble fleets and equipment). Therefore, the game state manipulation can be performed in the event dispatch thread without any rendering lookup. The game state is also used to display various aggregated information to the user.
However, as I need to introduce simulation (for example, building progress, population changes, fleet movements, manufacturing process, etc.), changing the game state in a Timer and EDT will surely slow down the rendering.
Lets say the simulation/AI operation is performed in every 500ms and I use SwingWorker for the computation of about 250ms in length. How can I ensure, that there is no race condition regarding the game state reads between the simulation and the possible user interaction?
I know that the result of the simulation (which is small amount of data) can be efficiently moved back to the EDT via the SwingUtilities.invokeLater() call.
The game state model seems to be too complex to be infeasible for just using immutable value classes everywhere.
Is there a relatively correct approach to eliminate this read race condition? Perhaps doing a full/partial game state cloning on every timer tick or change the living space of the game state from EDT into some other thread?
Update: (from the comments I gave)
The game operates with 13 AI controlled players, 1 human player and has about 10000 game objects (planets, buildings, equipment, research, etc.). A game object for example has the following attributes:
World (Planets, Players, Fleets, ...)
Planet (location, owner, population, type,
map, buildings, taxation, allocation, ...)
Building (location, enabled, energy, worker, health, ...)
In a scenario, the user builds a new building onto this planet. This is performed in EDT as the map and buildings collection needs to be changed. Parallel to this, a simulation is run on every 500ms to compute the energy allocation to the buildings on all game planets, which needs to traverse the buildings collection for statistics gathering. If the allocation is computed, it is submitted to the EDT and each building's energy field gets assigned.
Only human player interactions have this property, because the results of the AI computation are applied to the structures in EDT anyway.
In general, 75% of the object attributes are static and used only for rendering. The rest of it is changeable either via user interaction or simulation/AI decision. It is also ensured, that no new simulation/AI step is started until the previous one has written back all changes.
My objectives are:
Avoid delaying the user interaction, e.g. user places the building onto the planet and only after 0.5s gets the visual feedback
Avoid blocking the EDT with computation, lock wait, etc.
Avoid concurrency issues with collection traversal and modification, attribute changes
Options:
Fine grained object locking
Immutable collections
Volatile fields
Partial snapshot
All of these have advantages, disadvantages and causes to the model and the game.
Update 2: I'm talking about this game. My clone is here. The screenshots might help to imagine the rendering and data model interactions.
Update 3:
I'll try to give a small code sample for clarify my problem as it seems from the comments it is misunderstood:
List<GameObject> largeListOfGameObjects = ...
List<Building> preFilteredListOfBuildings = ...
// In EDT
public void onAddBuildingClicked() {
Building b = new Building(100 /* kW */);
largeListOfGameObjects.add(b);
preFilteredListOfBuildings.add(b);
}
// In EDT
public void paint(Graphics g) {
int y = 0;
for (Building b : preFilteredListOfBuildings) {
g.drawString(Integer.toString(b.powerAssigned), 0, y);
y += 20;
}
}
// In EDT
public void assignPowerTo(Building b, int amount) {
b.powerAssigned = amount;
}
// In simulation thread
public void distributePower() {
int sum = 0;
for (Building b : preFilteredListOfBuildings) {
sum += b.powerRequired;
}
final int alloc = sum / (preFilteredListOfBuildings.size() + 1);
for (final Building b : preFilteredListOfBuildings) {
SwingUtilities.invokeLater(=> assignPowerTo(b, alloc));
}
}
So the overlapping is between the onAddBuildingClicked() and distributePower(). Now imagine the case where you have 50 of these kind of overlappings between various parts of the game model.
This sounds like it could benefit from a client/server approach:
The player is a client - interactivity and rendering happen on that end. So the player presses a button, the request goes to the server. The reply from the server comes back, and the player's state is updated. At any point between these things happening, the screen can be re-painted, and it reflects the state of the game as the client currently knows it.
The AI is likewise a client - it's the equivalent of a bot.
The simulation is the server. It gets updates from its clients at various times and updates the state of the world, then sends out these updates to everyone as appropriate. Here's where it ties in with your situation: The simulation/AI requires a static world, and many things are happening at once. The server can simply queue up change requests and apply them before sending the updates back to the client(s). So as far as the server's concerned, the game world isn't actually changing in real time, it's changing whenever the server darn well decides it is.
Finally, on the client side, you can prevent the delay between pressing the button and seeing a result by doing some quick approximate calculations and displaying a result (so the immediate need is met) and then displaying the more correct result when the server gets around to talking to you.
Note that this does not actually have to be implemented in a TCP/IP over-the-internet sort of way, just that it helps to think of it in those terms.
Alternately, you can place the responsibility for keeping the data coherent during the simulation on a database, as they're already built with locking and coherency in mind. Something like sqlite could work as part of a non-networked solution.
Not sure I fully understand the behavior you are looking for, but it sounds like you need something like a state change thread/queue so all state changes are handled by a single thread.
Create an api, maybe like SwingUtilities.invokeLater() and/or SwingUtilities.invokeAndWait() for your state change queue to handle your state change requests.
How that is reflected in the gui I think depends on the behavior you are looking for. i.e. Can't withdraw money because current state is $0, or pop back to the user that the account was empty when the withdraw request was processed. (probably not with that terminology ;-) )
The easiest approach is to make the simulation fast enough to run in the EDT. Prefer programs that work!
For the two-thread model, what I suggest is synchronise the domain model with a rendering model. The render model should keep data on what came from the domain model.
For an update: In the simulation thread lock the render model. Traverse the render model updating where things are different from what is expected update the render model. When finished traversing, unlock the render model and schedule a repaint. Note that in this approach you don't need a bazillion listeners.
The render model can have different depths. At one extreme it might be an image and the update operation is just to replace a single reference with the new image object (this wont handle, for instance, resizing or other superficial interaction very well). You might not bother checking whether an item has change and just update eveything.
If changing the game state is fast (once you know what to change it to) you can treat the game state like other Swing models and only change or view the state in the EDT. If changing the game state is not fast, then you can either synchronize state change and do it in swing worker/timer (but not the EDT) or you can do it in separate thread that you treat similarly to the EDT (at which point you look at using a BlockingQueue to handle change requests). The last is more useful if the UI never has to retrieve information from the game state but instead has the rendering changes sent via listeners or observers.
Is it possible to incrementally update the game state and still have a model that is consistent? For example recalculate for a subset of planet/player/fleet objects in between renders/user updates.
If so, you could run incremental updates in the EDT that only calculate a small part of the state before allowing the EDT to process user inputs and render.
Following each incremental update in the EDT you would need to remember how much of the model remains to be updated and schedule a new SwingWorker on the EDT to continue this processing after any pending user inputs and rendering has been performed.
This should allow you to avoid copying or locking the game model while still keeping the user interactions responsive.
I think you shouldn't have World store any data or make changes to any objects itself, it should only be used to maintain a reference to an object and when that object needs to be changed, have the Player making the change change it directly. In this event, the only thing you need to do is synchronize each object in the game world so that when a Player is making a change, no other Player can do so. Here's an example of what I'm thinking:
Player A needs to know about a Planet, so it asks World for that Planet (how is dependent upon your implementation). World returns a reference to the Planet object Player A asked for. Player A decides to make a change, so it does so. Let's say it adds a building. The method to add a building to the Planet is synchronized so only one player can do so at a time. The building will keep track of its own construction time (if any) so the Planet's add building method would be freed up almost immediately. This way multiple players can ask for information on the same planet at the same time without affecting each other and players can add buildings almost simultaneously without much appearance of lag. If two players are looking for a place to put the building (if that is part of your game), then checking the suitability of a location will be a query not a change.
I'm sorry if this doesn't answer you're question, I'm not sure if I understood it correctly.
How about implementing a pipes and filters architecture. Pipes connect filters together and queue requests if the filter is not fast enough. Processing happens inside filters. The first filter is the AI engine while the rendering engine is implemented by a set of subsequent filters.
On every timer tick, the new dynamic world state is computed based on all the inputs (Time is also an input) and a copy inserted into the first pipe.
In the simplest case your rendering engine is implemented as a single filter. It just takes the state snapshots from the input pipe and renders it together with the static state. In a live game, the rendering engine may want to skip states if there are more than one in the pipe while if you're doing a benchmark or outputting a video you'll want to render every one.
The more filters you can decompose your rendering engine into, the better the parallelism will be. Maybe it is even possible to decompose the AI engine, e.g. you may want to separate dynamic state into fast changing and slow changing state.
This architecture gives you good parallelism without a lot of synchronization.
A problem with this architecture is that garbage collection is going to run frequently freezing all the threads every time, possible killing any advantage gained from multi-threading.
It looks like you need a priorityqueue to put the updates to the model on, in which updates frmo the user have priority over the updates from the simulation and other inputs. What I hear you saying is that the user always needs immediate feedback over his actions wheras the other inputs (simulation, otherwise) could have workers that may take longer than one simulation step.
Then synchronize on the priorityqueue.