Loading in a separate Thread

Started by CodeBunny, May 12, 2011, 15:15:16

Previous topic - Next topic

CodeBunny

I'm trying to create a class that performs actions in a separate thread, and can report on its progress while doing so. The general threading I've gotten together, but since each thread has a different context it's not letting me load OpenGL resources (images, fonts, etc.), which is the primary intended purpose for this class.

I looked through the docs and a SharedDrawable seems like the logical thing to use, so I attempted the following:

protected void shareContext()
{
	try
	{
		Drawable drawable = Display.getDrawable();
		sharedDrawable = new SharedDrawable(drawable);
		sharedDrawable.makeCurrent();
	}
	catch (LWJGLException e)
	{
		e.printStackTrace();
	}
}


However, this causes the following exception:

org.lwjgl.LWJGLException: Could not share contexts
	at org.lwjgl.opengl.WindowsContextImplementation.nCreate(Native Method)
	at org.lwjgl.opengl.WindowsContextImplementation.create(WindowsContextImplementation.java:50)
	at org.lwjgl.opengl.Context.<init>(Context.java:131)
	at org.lwjgl.opengl.AbstractDrawable.createSharedContext(AbstractDrawable.java:30)
	at org.lwjgl.opengl.SharedDrawable.<init>(SharedDrawable.java:50)


So, I think I don't really understand what I'm supposed to do to load OpenGL resources in another thread. Could someone explain how to do this a little better?

FYI, I'm using the Slick-Util texture loading methods.

spasi

Could you try if the BackgroundLoadTest works on your machine? It's in the LWJGL test package, class: org.lwjgl.test.opengl.multithread.BackgroundLoadTest. If it works, then have a look at that code, it should be helpful. If not, this could be an LWJGL bug and I'd like more info to find out what happens.

CodeBunny

Same problem:

Setting display mode to: 1024 x 768 x 16 @60Hz
-- Background Thread started --
** Sleeping, no texture created yet **
Exception in thread "Thread-1" java.lang.RuntimeException: org.lwjgl.LWJGLException: Could not share contexts
	at BackgroundLoading.BackgroundLoader$1.run(BackgroundLoader.java:93)
	at java.lang.Thread.run(Unknown Source)
Caused by: org.lwjgl.LWJGLException: Could not share contexts
	at org.lwjgl.opengl.WindowsContextImplementation.nCreate(Native Method)
	at org.lwjgl.opengl.WindowsContextImplementation.create(WindowsContextImplementation.java:50)
	at org.lwjgl.opengl.Context.<init>(Context.java:131)
	at org.lwjgl.opengl.AbstractDrawable.createSharedContext(AbstractDrawable.java:30)
	at org.lwjgl.opengl.SharedDrawable.<init>(SharedDrawable.java:50)
	at BackgroundLoading.BackgroundLoadTest$2.getDrawable(BackgroundLoadTest.java:205)
	at BackgroundLoading.BackgroundLoader$1.run(BackgroundLoader.java:90)
	... 1 more

spasi

- Does it work with a pbuffer? Pass "PB" instead of "SD" to the test.

- Judging by the error message it seems like your GPU driver doesn't support WGL_ARB_create_context (OpenGL 3.0+). Is that correct? What GPU is it and what driver version is installed?

CodeBunny

It does not support a pBuffer, either. I get the same error.

How do I detect GPU and driver? Both are Intel, I know that, and I have  the following information on the Graphics Control Panel:
Driver Version: 8.15.10.2202
Processor: x86 Family 6 Model 37 Stepping 5
Accelerator in use: Intel(R) HD Graphics

spasi

It may be a driver issue or the GPU simply can't do it. Try updating the driver.

CodeBunny

I'm trying. :\ Here's hoping my Dell will support an nVidia driver...

CodeBunny

Well, apparently my PoS Intel Driver can't support most OpenGL 3.0 functionality. The latest driver for my hardware doesn't work.

However, since I would like to have this functionality supported, can someone tell me if this code works for loading Textures and sounds?

protected SharedDrawable sharedDrawable;
	private static final Object lock = new Object();
	
	public void run()
	{
		synchronized (lock)
		{
			shareContext();
			// Do stuff
			releaseContext();
		}
		progress = total;
	}

	protected void shareContext()
	{
		try
		{
			Drawable drawable = Display.getDrawable();
			sharedDrawable = new SharedDrawable(drawable);
			sharedDrawable.makeCurrent();
		}
		catch (LWJGLException e)
		{
			e.printStackTrace();
		}
	}
	
	protected void releaseContext()
	{
		sharedDrawable.destroy();
	}


I have no way of testing functionality of my end, apparently, so I'd like an affirmation that this is the correct way of doing this.

spasi

Looks OK. I don't think you need the lock there btw.

I would advise against doing it blindly though. You really need to test this on a machine with an NV/AMD GPU. Multithreaded rendering (or even simple multithreaded resource loading) usually takes a lot of testing to get right.

CodeBunny

Oh, really? It was in BackgroundLoader so I thought I'd better implement it.

I know, and I'll try to do some outside testing. Thankfully, the only thing I really want to have happen is loading (and not using) of the desired resources, and that shouldn't be too difficult to test.

I've altered the class to include checks if the threaded loading worked or not. This way, if the loading crashes, the developer can delegate to loading the images in the main Thread.