From: <sp...@us...> - 2012-12-18 11:23:00
|
Revision: 3836 http://java-game-lib.svn.sourceforge.net/java-game-lib/?rev=3836&view=rev Author: spasi Date: 2012-12-18 11:22:52 +0000 (Tue, 18 Dec 2012) Log Message: ----------- Fixed BackgroundLoadTest to work on NV/Intel and improved context synchronization. Modified Paths: -------------- trunk/LWJGL/src/java/org/lwjgl/test/opengl/multithread/BackgroundLoader.java Modified: trunk/LWJGL/src/java/org/lwjgl/test/opengl/multithread/BackgroundLoader.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/test/opengl/multithread/BackgroundLoader.java 2012-12-17 11:58:48 UTC (rev 3835) +++ trunk/LWJGL/src/java/org/lwjgl/test/opengl/multithread/BackgroundLoader.java 2012-12-18 11:22:52 UTC (rev 3836) @@ -40,26 +40,33 @@ import org.lwjgl.BufferUtils; import org.lwjgl.LWJGLException; import org.lwjgl.opengl.Drawable; +import org.lwjgl.opengl.GLContext; +import org.lwjgl.opengl.GLSync; import org.lwjgl.util.Color; import org.lwjgl.util.ReadableColor; import java.nio.ByteBuffer; +import java.util.concurrent.locks.ReentrantLock; import static org.lwjgl.opengl.GL11.*; +import static org.lwjgl.opengl.GL32.*; abstract class BackgroundLoader { - private static final int WIDTH = 32; + private static final int WIDTH = 32; private static final int HEIGHT = 32; - private static final Object lock = new Object(); + // CPU synchronization + private final ReentrantLock lock = new ReentrantLock(); + // GPU synchronization + private GLSync fence; private Drawable drawable; private boolean running; private ByteBuffer texture; - private int texID; + private int texID; protected BackgroundLoader() { running = true; @@ -73,6 +80,9 @@ } void start() throws LWJGLException { + // The shared context must be created on the main thread. + drawable = getDrawable(); + new Thread(new Runnable() { public void run() { System.out.println("-- Background Thread started --"); @@ -86,7 +96,7 @@ } try { - drawable = getDrawable(); + // Make the shared context current in the worker thread drawable.makeCurrent(); } catch (LWJGLException e) { throw new RuntimeException(e); @@ -94,20 +104,30 @@ System.out.println("** Drawable created **"); - synchronized ( lock ) { - // Create a "dummy" texture while we wait for texture IO - createCheckerTexture(Color.RED, Color.WHITE, 2); + // Create a "dummy" texture while we wait for texture IO + createCheckerTexture(Color.RED, Color.WHITE, 2); - texID = glGenTextures(); - glBindTexture(GL_TEXTURE_2D, texID); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, WIDTH, HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, texture); + lock.lock(); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + texID = glGenTextures(); + glBindTexture(GL_TEXTURE_2D, texID); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, WIDTH, HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, texture); - glBindTexture(GL_TEXTURE_2D, 0); - } + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glBindTexture(GL_TEXTURE_2D, 0); + + // OpenGL commands from different contexts may be executed in any order. So we need a way to synchronize + final boolean useFences = GLContext.getCapabilities().OpenGL32; + + if ( useFences ) + fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); + else + glFlush(); // Best we can do without fences. This will force rendering on the main thread to happen after we upload the texture. + + lock.unlock(); + System.out.println("** Dummy texture created **"); long lastTextureCreated = System.currentTimeMillis(); // Delay first texture creation @@ -129,14 +149,23 @@ else createGradientTexture(Color.GREEN, Color.YELLOW); + lock.lock(); + glBindTexture(GL_TEXTURE_2D, texID); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, WIDTH, HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, texture); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glBindTexture(GL_TEXTURE_2D, 0); + if ( useFences ) + fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); + else + glFlush(); + + lock.unlock(); + System.out.println("** Created new gradient texture **"); lastTextureCreated = System.currentTimeMillis(); @@ -151,8 +180,15 @@ } int getTexID() { - synchronized ( lock ) { + lock.lock(); + try { + if ( fence != null ) { + glWaitSync(fence, 0, GL_TIMEOUT_IGNORED); + fence = null; + } return texID; + } finally { + lock.unlock(); } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |