OpenGLES preloading textures in other thread - java

I NEED to preload some textures in the non-main-thread of an OpenGLES application. I read this: Can't call glGenTextures on multithreaded android app but its more the Java version of what I need. How do I tell my loading Thread to upload/create a texture into the main loop? I read something about creating a context and share with the main context somehow. How?

There are two steps to get textures from resources/disk to rendering in GL, and they can be separated to allow most of the loading and computational work on a worker thread.
The first step is the actual creation of a Bitmap at the Java level, which will use something like BitmapFactory.decodeResouce(). This part can be done on any thread you like, and when you're done loading you throw that bitmap into an ArrayList or queue or whatever. Make sure you surround the access of the list with a synchronized block.
The second step is to call glGenTextures, which has to be done in the GL thread. So at the beginning of your drawFrame() method, check the size of that ArrayList you're saving bitmaps to, and if the size is bigger than 0, make some calls to glGenTexures and remove and recycyle the bitmaps from the array.

Related

LWJGL: pass OpenGL context between threads

I have two threads running in my program. When I try to use OpenGL functions in the thread that is not my main, it throws an IllegalStateException:No OpenGL context is current in the current thread. So my question is, how do I pass the context from the main thread to a different thread? I am using LWJGL 3.
I think I solved it but I'm not 100% sure it's the best way to do it. You have to call GLFW.glfwMakeContextCurrent(MemoryUtil.NULL); in the thread you want to depart from, then call GLFW.glfwMakeContextCurrent(window); GLContext.createFromCurrent(); from the thread you want to switch to.
Take a look at this example. It uses a Drawable that you can use in your two Java Threads. I'm not entirely sure if it still works since a lot of this class is associated with LWJGL 2. I'll test it soon and let you know if this or your method is more efficient (Gonna create a tiny micro-benchmark :) .

Send VBO to GPU in separate thread

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.

glReadPixel doesn't work in OnPick function

i try to implement 3D picking in an android app. I use OpenGL ES2.0.
Now I want to read the depth buffer (which is written in an FBO) but glReadPixels returns only 0.
The code is correct, because I tried the same code after calling my RenderInTexture function and it returns the correct values.
Calling RenderInTexture in the OnPick function and than call glReadPixels returns also 0.
What is the problem?
Isn't it possible to read a framebuffer in the OnPick event or do i have to set some variables?
Thanks for help.
Is the OnPick called on the main (UI) thread? Probably you have two threads, the opengl rendering thread and the main application thread where events are sent. Try storing the onpick coordinates in you OnPick method and do the computation in the opengl thread.
Hope that helps.

Updating scenes in advance while still rendering previous frame

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.

multithreading for java graphics

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).

Categories