implemented LWJGL3 BufferAllocator

native-compilation-test
javasabr 8 years ago
parent 8d818a21bc
commit d468c20fba
  1. 31
      jme3-core/src/main/java/com/jme3/util/BufferAllocatorFactory.java
  2. 50
      jme3-core/src/main/java/com/jme3/util/BufferUtils.java
  3. 82
      jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglContext.java
  4. 24
      jme3-lwjgl3/src/main/java/com/jme3/util/LWJGLBufferAllocator.java

@ -0,0 +1,31 @@
package com.jme3.util;
import com.jme3.system.Annotations.Internal;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* The factory of buffer allocators.
*
* @author JavaSaBR
*/
@Internal
public class BufferAllocatorFactory {
public static final String PROPERTY_BUFFER_ALLOCATOR_IMPLEMENTATION = "com.jme3.BufferAllocatorImplementation";
private static final Logger LOGGER = Logger.getLogger(BufferAllocatorFactory.class.getName());
@Internal
protected static BufferAllocator create() {
final String className = System.getProperty(PROPERTY_BUFFER_ALLOCATOR_IMPLEMENTATION, ReflectionAllocator.class.getName());
try {
return (BufferAllocator) Class.forName(className).newInstance();
} catch (final Throwable e) {
LOGGER.log(Level.WARNING, "Unable to access {0}", className);
return new PrimitiveAllocator();
}
}
}

@ -31,6 +31,12 @@
*/ */
package com.jme3.util; package com.jme3.util;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.math.Vector4f;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.lang.ref.PhantomReference; import java.lang.ref.PhantomReference;
import java.lang.ref.Reference; import java.lang.ref.Reference;
@ -45,12 +51,6 @@ import java.nio.LongBuffer;
import java.nio.ShortBuffer; import java.nio.ShortBuffer;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.math.Vector4f;
/** /**
* <code>BufferUtils</code> is a helper class for generating nio buffers from * <code>BufferUtils</code> is a helper class for generating nio buffers from
* jME data classes such as Vectors and ColorRGBA. * jME data classes such as Vectors and ColorRGBA.
@ -59,7 +59,11 @@ import com.jme3.math.Vector4f;
* @version $Id: BufferUtils.java,v 1.16 2007/10/29 16:56:18 nca Exp $ * @version $Id: BufferUtils.java,v 1.16 2007/10/29 16:56:18 nca Exp $
*/ */
public final class BufferUtils { public final class BufferUtils {
private static BufferAllocator allocator = new PrimitiveAllocator();
/**
* The field should be final to support thread-safe.
*/
private static final BufferAllocator ALLOCATOR = BufferAllocatorFactory.create();
private static boolean trackDirectMemory = false; private static boolean trackDirectMemory = false;
private static ReferenceQueue<Buffer> removeCollected = new ReferenceQueue<Buffer>(); private static ReferenceQueue<Buffer> removeCollected = new ReferenceQueue<Buffer>();
@ -68,26 +72,6 @@ public final class BufferUtils {
private static boolean used; private static boolean used;
static {
try {
allocator = new ReflectionAllocator();
} catch (Throwable t) {
t.printStackTrace();
System.err.println("Error using ReflectionAllocator");
}
}
/**
* Warning! do only set this before JME is started!
*/
public static void setAllocator(BufferAllocator allocator) {
if (used) {
throw new IllegalStateException(
"An Buffer was already allocated, since it is quite likely that other dispose methods will create native dangling pointers or other fun things, this is forbidden to be changed at runtime");
}
BufferUtils.allocator = allocator;
}
/** /**
* Set it to true if you want to enable direct memory tracking for debugging * Set it to true if you want to enable direct memory tracking for debugging
* purpose. Default is false. To print direct memory usage use * purpose. Default is false. To print direct memory usage use
@ -809,7 +793,7 @@ public final class BufferUtils {
* @return the new DoubleBuffer * @return the new DoubleBuffer
*/ */
public static DoubleBuffer createDoubleBuffer(int size) { public static DoubleBuffer createDoubleBuffer(int size) {
DoubleBuffer buf = allocator.allocate(8 * size).order(ByteOrder.nativeOrder()).asDoubleBuffer(); DoubleBuffer buf = ALLOCATOR.allocate(8 * size).order(ByteOrder.nativeOrder()).asDoubleBuffer();
buf.clear(); buf.clear();
onBufferAllocated(buf); onBufferAllocated(buf);
return buf; return buf;
@ -872,7 +856,7 @@ public final class BufferUtils {
* @return the new FloatBuffer * @return the new FloatBuffer
*/ */
public static FloatBuffer createFloatBuffer(int size) { public static FloatBuffer createFloatBuffer(int size) {
FloatBuffer buf = allocator.allocate(4 * size).order(ByteOrder.nativeOrder()).asFloatBuffer(); FloatBuffer buf = ALLOCATOR.allocate(4 * size).order(ByteOrder.nativeOrder()).asFloatBuffer();
buf.clear(); buf.clear();
onBufferAllocated(buf); onBufferAllocated(buf);
return buf; return buf;
@ -934,7 +918,7 @@ public final class BufferUtils {
* @return the new IntBuffer * @return the new IntBuffer
*/ */
public static IntBuffer createIntBuffer(int size) { public static IntBuffer createIntBuffer(int size) {
IntBuffer buf = allocator.allocate(4 * size).order(ByteOrder.nativeOrder()).asIntBuffer(); IntBuffer buf = ALLOCATOR.allocate(4 * size).order(ByteOrder.nativeOrder()).asIntBuffer();
buf.clear(); buf.clear();
onBufferAllocated(buf); onBufferAllocated(buf);
return buf; return buf;
@ -997,7 +981,7 @@ public final class BufferUtils {
* @return the new IntBuffer * @return the new IntBuffer
*/ */
public static ByteBuffer createByteBuffer(int size) { public static ByteBuffer createByteBuffer(int size) {
ByteBuffer buf = allocator.allocate(size).order(ByteOrder.nativeOrder()); ByteBuffer buf = ALLOCATOR.allocate(size).order(ByteOrder.nativeOrder());
buf.clear(); buf.clear();
onBufferAllocated(buf); onBufferAllocated(buf);
return buf; return buf;
@ -1079,7 +1063,7 @@ public final class BufferUtils {
* @return the new ShortBuffer * @return the new ShortBuffer
*/ */
public static ShortBuffer createShortBuffer(int size) { public static ShortBuffer createShortBuffer(int size) {
ShortBuffer buf = allocator.allocate(2 * size).order(ByteOrder.nativeOrder()).asShortBuffer(); ShortBuffer buf = ALLOCATOR.allocate(2 * size).order(ByteOrder.nativeOrder()).asShortBuffer();
buf.clear(); buf.clear();
onBufferAllocated(buf); onBufferAllocated(buf);
return buf; return buf;
@ -1292,7 +1276,7 @@ public final class BufferUtils {
if (!isDirect(toBeDestroyed)) { if (!isDirect(toBeDestroyed)) {
return; return;
} }
allocator.destroyDirectBuffer(toBeDestroyed); ALLOCATOR.destroyDirectBuffer(toBeDestroyed);
} }
/* /*

@ -32,6 +32,10 @@
package com.jme3.system.lwjgl; package com.jme3.system.lwjgl;
import static org.lwjgl.opencl.CL10.CL_CONTEXT_PLATFORM;
import static org.lwjgl.opengl.GL.createCapabilities;
import static org.lwjgl.opengl.GL11.glGetInteger;
import com.jme3.input.lwjgl.GlfwJoystickInput; import com.jme3.input.lwjgl.GlfwJoystickInput;
import com.jme3.input.lwjgl.GlfwKeyInput; import com.jme3.input.lwjgl.GlfwKeyInput;
import com.jme3.input.lwjgl.GlfwMouseInput; import com.jme3.input.lwjgl.GlfwMouseInput;
@ -48,14 +52,24 @@ import com.jme3.renderer.lwjgl.LwjglGL;
import com.jme3.renderer.lwjgl.LwjglGLExt; import com.jme3.renderer.lwjgl.LwjglGLExt;
import com.jme3.renderer.lwjgl.LwjglGLFboEXT; import com.jme3.renderer.lwjgl.LwjglGLFboEXT;
import com.jme3.renderer.lwjgl.LwjglGLFboGL3; import com.jme3.renderer.lwjgl.LwjglGLFboGL3;
import com.jme3.renderer.opengl.*; import com.jme3.renderer.opengl.GL;
import com.jme3.system.*; import com.jme3.renderer.opengl.GL2;
import java.nio.IntBuffer; import com.jme3.renderer.opengl.GL3;
import java.util.ArrayList; import com.jme3.renderer.opengl.GL4;
import java.util.List; import com.jme3.renderer.opengl.GLDebugDesktop;
import java.util.concurrent.atomic.AtomicBoolean; import com.jme3.renderer.opengl.GLExt;
import java.util.logging.Level; import com.jme3.renderer.opengl.GLFbo;
import java.util.logging.Logger; import com.jme3.renderer.opengl.GLRenderer;
import com.jme3.renderer.opengl.GLTiming;
import com.jme3.renderer.opengl.GLTimingState;
import com.jme3.renderer.opengl.GLTracer;
import com.jme3.system.AppSettings;
import com.jme3.system.JmeContext;
import com.jme3.system.SystemListener;
import com.jme3.system.Timer;
import com.jme3.util.BufferAllocatorFactory;
import com.jme3.util.LWJGLBufferAllocator;
import org.lwjgl.PointerBuffer; import org.lwjgl.PointerBuffer;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
import org.lwjgl.opencl.*; import org.lwjgl.opencl.*;
@ -63,18 +77,25 @@ import org.lwjgl.opengl.ARBDebugOutput;
import org.lwjgl.opengl.ARBFramebufferObject; import org.lwjgl.opengl.ARBFramebufferObject;
import org.lwjgl.opengl.EXTFramebufferMultisample; import org.lwjgl.opengl.EXTFramebufferMultisample;
import org.lwjgl.opengl.GLCapabilities; import org.lwjgl.opengl.GLCapabilities;
import org.lwjgl.system.Platform;
import static org.lwjgl.glfw.GLFW.GLFW_TRUE; import java.nio.IntBuffer;
import static org.lwjgl.opencl.CL10.CL_CONTEXT_PLATFORM; import java.util.ArrayList;
import static org.lwjgl.opengl.GL.createCapabilities; import java.util.List;
import static org.lwjgl.opengl.GL11.glGetInteger; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import java.util.logging.Logger;
/** /**
* A LWJGL implementation of a graphics context. * A LWJGL implementation of a graphics context.
*/ */
public abstract class LwjglContext implements JmeContext { public abstract class LwjglContext implements JmeContext {
private static final Logger logger = Logger.getLogger(LwjglContext.class.getName()); private static final Logger LOGGER = Logger.getLogger(LwjglContext.class.getName());
static {
System.setProperty(BufferAllocatorFactory.PROPERTY_BUFFER_ALLOCATOR_IMPLEMENTATION, LWJGLBufferAllocator.class.getName());
}
public static final boolean CL_GL_SHARING_POSSIBLE = true; public static final boolean CL_GL_SHARING_POSSIBLE = true;
@ -99,8 +120,8 @@ public abstract class LwjglContext implements JmeContext {
} }
protected void printContextInitInfo() { protected void printContextInitInfo() {
logger.log(Level.INFO, "LWJGL {0} context running on thread {1}\n" LOGGER.log(Level.INFO, "LWJGL {0} context running on thread {1}\n"
+ " * Graphics Adapter: GLFW {2}", + " * Graphics Adapter: GLFW {2}",
new Object[]{org.lwjgl.Version.getVersion(), Thread.currentThread().getName(), GLFW.glfwGetVersionString()}); new Object[]{org.lwjgl.Version.getVersion(), Thread.currentThread().getName(), GLFW.glfwGetVersionString()});
} }
@ -121,7 +142,7 @@ public abstract class LwjglContext implements JmeContext {
samples = settings.getSamples(); samples = settings.getSamples();
final int supportedSamples = determineMaxSamples(); final int supportedSamples = determineMaxSamples();
if (supportedSamples < samples) { if (supportedSamples < samples) {
logger.log(Level.WARNING, LOGGER.log(Level.WARNING,
"Couldn't satisfy antialiasing samples requirement: x{0}. " "Couldn't satisfy antialiasing samples requirement: x{0}. "
+ "Video hardware only supports: x{1}", + "Video hardware only supports: x{1}",
new Object[]{samples, supportedSamples}); new Object[]{samples, supportedSamples});
@ -205,8 +226,6 @@ public abstract class LwjglContext implements JmeContext {
* *
* Copied from the old release * Copied from the old release
* *
* @param filter the platform filter
*
* @return the available platforms * @return the available platforms
*/ */
private static long[] getPlatforms() { private static long[] getPlatforms() {
@ -233,12 +252,12 @@ public abstract class LwjglContext implements JmeContext {
} }
protected void initOpenCL(long window) { protected void initOpenCL(long window) {
logger.info("Initialize OpenCL with LWJGL3"); LOGGER.info("Initialize OpenCL with LWJGL3");
// try { // try {
// CL.create(); // CL.create();
// } catch (Exception ex) { // } catch (Exception ex) {
// logger.log(Level.SEVERE, "Unable to initialize OpenCL", ex); // LOGGER.log(Level.SEVERE, "Unable to initialize OpenCL", ex);
// return; // return;
// } // }
@ -279,7 +298,7 @@ public abstract class LwjglContext implements JmeContext {
platformInfos.append("\n * * Supports interop: ").append(device.hasOpenGLInterop()); platformInfos.append("\n * * Supports interop: ").append(device.hasOpenGLInterop());
} }
} }
logger.info(platformInfos.toString()); LOGGER.info(platformInfos.toString());
//choose devices //choose devices
PlatformChooser chooser = null; PlatformChooser chooser = null;
@ -287,7 +306,7 @@ public abstract class LwjglContext implements JmeContext {
try { try {
chooser = (PlatformChooser) Class.forName(settings.getOpenCLPlatformChooser()).newInstance(); chooser = (PlatformChooser) Class.forName(settings.getOpenCLPlatformChooser()).newInstance();
} catch (Exception ex) { } catch (Exception ex) {
logger.log(Level.WARNING, "unable to instantiate custom PlatformChooser", ex); LOGGER.log(Level.WARNING, "unable to instantiate custom PlatformChooser", ex);
} }
} }
if (chooser == null) { if (chooser == null) {
@ -298,35 +317,35 @@ public abstract class LwjglContext implements JmeContext {
LwjglPlatform platform = null; LwjglPlatform platform = null;
for (Device d : choosenDevices) { for (Device d : choosenDevices) {
if (!(d instanceof LwjglDevice)) { if (!(d instanceof LwjglDevice)) {
logger.log(Level.SEVERE, "attempt to return a custom Device implementation from PlatformChooser: {0}", d); LOGGER.log(Level.SEVERE, "attempt to return a custom Device implementation from PlatformChooser: {0}", d);
return; return;
} }
LwjglDevice ld = (LwjglDevice) d; LwjglDevice ld = (LwjglDevice) d;
if (platform == null) { if (platform == null) {
platform = ld.getPlatform(); platform = ld.getPlatform();
} else if (platform != ld.getPlatform()) { } else if (platform != ld.getPlatform()) {
logger.severe("attempt to use devices from different platforms"); LOGGER.severe("attempt to use devices from different platforms");
return; return;
} }
devices.add(ld.getDevice()); devices.add(ld.getDevice());
} }
if (devices.isEmpty()) { if (devices.isEmpty()) {
logger.warning("no devices specified, no OpenCL context created"); LOGGER.warning("no devices specified, no OpenCL context created");
return; return;
} }
logger.log(Level.INFO, "chosen platform: {0}", platform.getName()); LOGGER.log(Level.INFO, "chosen platform: {0}", platform.getName());
logger.log(Level.INFO, "chosen devices: {0}", choosenDevices); LOGGER.log(Level.INFO, "chosen devices: {0}", choosenDevices);
//create context //create context
try { try {
long c = createContext(platform.getPlatform(), devices, window); long c = createContext(platform.getPlatform(), devices, window);
clContext = new com.jme3.opencl.lwjgl.LwjglContext(c, (List<LwjglDevice>) choosenDevices); clContext = new com.jme3.opencl.lwjgl.LwjglContext(c, (List<LwjglDevice>) choosenDevices);
} catch (Exception ex) { } catch (final Exception ex) {
logger.log(Level.SEVERE, "Unable to create OpenCL context", ex); LOGGER.log(Level.SEVERE, "Unable to create OpenCL context", ex);
return; return;
} }
logger.info("OpenCL context created"); LOGGER.info("OpenCL context created");
} }
private long createContext(final long platform, final List<Long> devices, long window) throws Exception { private long createContext(final long platform, final List<Long> devices, long window) throws Exception {
@ -338,7 +357,7 @@ public abstract class LwjglContext implements JmeContext {
//https://github.com/glfw/glfw/issues/104 //https://github.com/glfw/glfw/issues/104
//https://github.com/LWJGL/lwjgl3/blob/master/modules/core/src/test/java/org/lwjgl/demo/opencl/Mandelbrot.java //https://github.com/LWJGL/lwjgl3/blob/master/modules/core/src/test/java/org/lwjgl/demo/opencl/Mandelbrot.java
//TODO: test on Linus and MacOSX //TODO: test on Linus and MacOSX
switch (org.lwjgl.system.Platform.get()) { switch (Platform.get()) {
case WINDOWS: case WINDOWS:
properties properties
.put(KHRGLSharing.CL_GL_CONTEXT_KHR) .put(KHRGLSharing.CL_GL_CONTEXT_KHR)
@ -446,5 +465,4 @@ public abstract class LwjglContext implements JmeContext {
public Context getOpenCLContext() { public Context getOpenCLContext() {
return clContext; return clContext;
} }
} }

@ -0,0 +1,24 @@
package com.jme3.util;
import org.lwjgl.system.MemoryUtil;
import java.nio.Buffer;
import java.nio.ByteBuffer;
/**
* The implementation of the {@link BufferAllocator} which use {@link MemoryUtil} to manage memory.
*
* @author JavaSaBr
*/
public class LWJGLBufferAllocator implements BufferAllocator {
@Override
public void destroyDirectBuffer(final Buffer buffer) {
MemoryUtil.memFree(buffer);
}
@Override
public ByteBuffer allocate(final int size) {
return MemoryUtil.memAlloc(size);
}
}
Loading…
Cancel
Save