added memory managing: native resources are now automatically released
This commit is contained in:
parent
0d003275a7
commit
0c47bf18c9
@ -37,7 +37,7 @@ import java.nio.ByteBuffer;
|
|||||||
*
|
*
|
||||||
* @author Sebastian Weiss
|
* @author Sebastian Weiss
|
||||||
*/
|
*/
|
||||||
public abstract class Buffer {
|
public abstract class Buffer implements OpenCLObject {
|
||||||
|
|
||||||
public abstract int getSize();
|
public abstract int getSize();
|
||||||
|
|
||||||
@ -154,4 +154,8 @@ public abstract class Buffer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public abstract Event copyToImageAsync(CommandQueue queue, Image dest, long srcOffset, long[] destOrigin, long[] destRegion);
|
public abstract Event copyToImageAsync(CommandQueue queue, Image dest, long srcOffset, long[] destOrigin, long[] destRegion);
|
||||||
|
|
||||||
|
public abstract Event acquireBufferForSharingAsync(CommandQueue queue);
|
||||||
|
public abstract Event releaseBufferForSharingAsync(CommandQueue queue);
|
||||||
|
//TODO: add variants of the above two methods that don't create the event object, but release the event immediately
|
||||||
}
|
}
|
||||||
|
@ -31,13 +31,11 @@
|
|||||||
*/
|
*/
|
||||||
package com.jme3.opencl;
|
package com.jme3.opencl;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Sebastian Weiss
|
* @author Sebastian Weiss
|
||||||
*/
|
*/
|
||||||
public interface CommandQueue {
|
public interface CommandQueue extends OpenCLObject {
|
||||||
|
|
||||||
void flush();
|
void flush();
|
||||||
|
|
||||||
|
@ -38,7 +38,6 @@ import com.jme3.opencl.Image.ImageDescriptor;
|
|||||||
import com.jme3.opencl.Image.ImageFormat;
|
import com.jme3.opencl.Image.ImageFormat;
|
||||||
import com.jme3.opencl.Image.ImageType;
|
import com.jme3.opencl.Image.ImageType;
|
||||||
import com.jme3.scene.VertexBuffer;
|
import com.jme3.scene.VertexBuffer;
|
||||||
import com.jme3.scene.mesh.IndexBuffer;
|
|
||||||
import com.jme3.texture.FrameBuffer;
|
import com.jme3.texture.FrameBuffer;
|
||||||
import com.jme3.texture.Texture;
|
import com.jme3.texture.Texture;
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
@ -55,7 +54,7 @@ import java.util.logging.Logger;
|
|||||||
*
|
*
|
||||||
* @author Sebastian Weiss
|
* @author Sebastian Weiss
|
||||||
*/
|
*/
|
||||||
public abstract class Context {
|
public abstract class Context implements OpenCLObject {
|
||||||
private static final Logger LOG = Logger.getLogger(Context.class.getName());
|
private static final Logger LOG = Logger.getLogger(Context.class.getName());
|
||||||
|
|
||||||
public abstract List<? extends Device> getDevices();
|
public abstract List<? extends Device> getDevices();
|
||||||
|
@ -35,7 +35,7 @@ package com.jme3.opencl;
|
|||||||
*
|
*
|
||||||
* @author Sebastian Weiss
|
* @author Sebastian Weiss
|
||||||
*/
|
*/
|
||||||
public interface Event {
|
public interface Event extends OpenCLObject {
|
||||||
|
|
||||||
void waitForFinished();
|
void waitForFinished();
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ import java.util.Objects;
|
|||||||
*
|
*
|
||||||
* @author Sebastian Weiss
|
* @author Sebastian Weiss
|
||||||
*/
|
*/
|
||||||
public interface Image {
|
public interface Image extends OpenCLObject {
|
||||||
|
|
||||||
public static enum ImageChannelType {
|
public static enum ImageChannelType {
|
||||||
SNORM_INT8,
|
SNORM_INT8,
|
||||||
@ -237,4 +237,5 @@ public interface Image {
|
|||||||
|
|
||||||
Event acquireImageForSharingAsync(CommandQueue queue);
|
Event acquireImageForSharingAsync(CommandQueue queue);
|
||||||
Event releaseImageForSharingAsync(CommandQueue queue);
|
Event releaseImageForSharingAsync(CommandQueue queue);
|
||||||
|
//TODO: add variants of the above two methods that don't create the event object, but release the event immediately
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ import java.nio.ByteBuffer;
|
|||||||
*
|
*
|
||||||
* @author Sebastian Weiss
|
* @author Sebastian Weiss
|
||||||
*/
|
*/
|
||||||
public abstract class Kernel {
|
public abstract class Kernel implements OpenCLObject {
|
||||||
protected final WorkSize globalWorkSize;
|
protected final WorkSize globalWorkSize;
|
||||||
protected final WorkSize workGroupSize;
|
protected final WorkSize workGroupSize;
|
||||||
|
|
||||||
@ -180,4 +180,6 @@ public abstract class Kernel {
|
|||||||
return Run(queue);
|
return Run(queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: add variants of the above three methods that don't create the event object, but release the event immediately
|
||||||
|
|
||||||
}
|
}
|
||||||
|
45
jme3-core/src/main/java/com/jme3/opencl/OpenCLObject.java
Normal file
45
jme3-core/src/main/java/com/jme3/opencl/OpenCLObject.java
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2016 jMonkeyEngine
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package com.jme3.opencl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Sebastian Weiss
|
||||||
|
*/
|
||||||
|
public interface OpenCLObject {
|
||||||
|
|
||||||
|
public static interface ObjectReleaser {
|
||||||
|
void release();
|
||||||
|
}
|
||||||
|
ObjectReleaser getReleaser();
|
||||||
|
|
||||||
|
}
|
118
jme3-core/src/main/java/com/jme3/opencl/OpenCLObjectManager.java
Normal file
118
jme3-core/src/main/java/com/jme3/opencl/OpenCLObjectManager.java
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2016 jMonkeyEngine
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package com.jme3.opencl;
|
||||||
|
|
||||||
|
import java.lang.ref.PhantomReference;
|
||||||
|
import java.lang.ref.ReferenceQueue;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Sebastian Weiss
|
||||||
|
*/
|
||||||
|
public class OpenCLObjectManager {
|
||||||
|
private static final Logger LOG = Logger.getLogger(OpenCLObjectManager.class.getName());
|
||||||
|
private static final Level LOG_LEVEL1 = Level.INFO;
|
||||||
|
private static final Level LOG_LEVEL2 = Level.INFO;
|
||||||
|
/**
|
||||||
|
* Call Runtime.getRuntime().gc() every these frames
|
||||||
|
*/
|
||||||
|
private static final int GC_FREQUENCY = 10;
|
||||||
|
|
||||||
|
private static final OpenCLObjectManager INSTANCE = new OpenCLObjectManager();
|
||||||
|
private OpenCLObjectManager() {}
|
||||||
|
|
||||||
|
public static OpenCLObjectManager getInstance() {
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ReferenceQueue<Object> refQueue = new ReferenceQueue<Object>();
|
||||||
|
private HashSet<OpenCLObjectRef> activeObjects = new HashSet<OpenCLObjectRef>();
|
||||||
|
private int gcCounter = 0;
|
||||||
|
|
||||||
|
private static class OpenCLObjectRef extends PhantomReference<Object> {
|
||||||
|
|
||||||
|
private OpenCLObject.ObjectReleaser releaser;
|
||||||
|
|
||||||
|
public OpenCLObjectRef(ReferenceQueue<Object> refQueue, OpenCLObject obj){
|
||||||
|
super(obj, refQueue);
|
||||||
|
releaser = obj.getReleaser();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerObject(OpenCLObject obj) {
|
||||||
|
OpenCLObjectRef ref = new OpenCLObjectRef(refQueue, obj);
|
||||||
|
activeObjects.add(ref);
|
||||||
|
LOG.log(LOG_LEVEL1, "registered OpenCL object: {0}", obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteObject(OpenCLObjectRef ref) {
|
||||||
|
LOG.log(LOG_LEVEL1, "deleting OpenCL object by: {0}", ref.releaser);
|
||||||
|
ref.releaser.release();
|
||||||
|
activeObjects.remove(ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteUnusedObjects() {
|
||||||
|
gcCounter++;
|
||||||
|
if (gcCounter >= GC_FREQUENCY) {
|
||||||
|
//The program is that the OpenCLObjects are so small that they are
|
||||||
|
//enqueued for finalization very late. Therefore, without this
|
||||||
|
//hack, we are running out of host memory on the OpenCL side quickly.
|
||||||
|
gcCounter = 0;
|
||||||
|
Runtime.getRuntime().gc();
|
||||||
|
}
|
||||||
|
|
||||||
|
int removed = 0;
|
||||||
|
while (true) {
|
||||||
|
// Remove objects reclaimed by GC.
|
||||||
|
OpenCLObjectRef ref = (OpenCLObjectRef) refQueue.poll();
|
||||||
|
if (ref == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
deleteObject(ref);
|
||||||
|
removed++;
|
||||||
|
}
|
||||||
|
if (removed >= 1) {
|
||||||
|
LOG.log(LOG_LEVEL2, "NativeObjectManager: {0} native objects were removed from native", removed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteAllObjects() {
|
||||||
|
for (OpenCLObjectRef ref : activeObjects) {
|
||||||
|
LOG.log(LOG_LEVEL1, "deleting OpenCL object by: {0}", ref.releaser);
|
||||||
|
ref.releaser.release();
|
||||||
|
}
|
||||||
|
activeObjects.clear();
|
||||||
|
}
|
||||||
|
}
|
@ -35,7 +35,7 @@ package com.jme3.opencl;
|
|||||||
*
|
*
|
||||||
* @author Sebastian Weiss
|
* @author Sebastian Weiss
|
||||||
*/
|
*/
|
||||||
public interface Program {
|
public interface Program extends OpenCLObject {
|
||||||
|
|
||||||
void build(String args) throws KernelCompilationException;
|
void build(String args) throws KernelCompilationException;
|
||||||
void build() throws KernelCompilationException;
|
void build() throws KernelCompilationException;
|
||||||
|
@ -35,6 +35,7 @@ import com.jme3.material.RenderState;
|
|||||||
import com.jme3.material.RenderState.StencilOperation;
|
import com.jme3.material.RenderState.StencilOperation;
|
||||||
import com.jme3.material.RenderState.TestFunction;
|
import com.jme3.material.RenderState.TestFunction;
|
||||||
import com.jme3.math.*;
|
import com.jme3.math.*;
|
||||||
|
import com.jme3.opencl.OpenCLObjectManager;
|
||||||
import com.jme3.renderer.*;
|
import com.jme3.renderer.*;
|
||||||
import com.jme3.scene.Mesh;
|
import com.jme3.scene.Mesh;
|
||||||
import com.jme3.scene.Mesh.Mode;
|
import com.jme3.scene.Mesh.Mode;
|
||||||
@ -552,6 +553,7 @@ public final class GLRenderer implements Renderer {
|
|||||||
public void cleanup() {
|
public void cleanup() {
|
||||||
logger.log(Level.FINE, "Deleting objects and invalidating state");
|
logger.log(Level.FINE, "Deleting objects and invalidating state");
|
||||||
objManager.deleteAllObjects(this);
|
objManager.deleteAllObjects(this);
|
||||||
|
OpenCLObjectManager.getInstance().deleteAllObjects();
|
||||||
statistics.clearMemory();
|
statistics.clearMemory();
|
||||||
invalidateState();
|
invalidateState();
|
||||||
}
|
}
|
||||||
@ -935,6 +937,7 @@ public final class GLRenderer implements Renderer {
|
|||||||
|
|
||||||
public void postFrame() {
|
public void postFrame() {
|
||||||
objManager.deleteUnused(this);
|
objManager.deleteUnused(this);
|
||||||
|
OpenCLObjectManager.getInstance().deleteUnusedObjects();
|
||||||
gl.resetStats();
|
gl.resetStats();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,6 +61,7 @@ public class TestWriteToTexture extends SimpleApplication implements AnalogListe
|
|||||||
private Vector2f C;
|
private Vector2f C;
|
||||||
private Image texCL;
|
private Image texCL;
|
||||||
private boolean dragging;
|
private boolean dragging;
|
||||||
|
private int gcCounter;
|
||||||
|
|
||||||
public static void main(String[] args){
|
public static void main(String[] args){
|
||||||
TestWriteToTexture app = new TestWriteToTexture();
|
TestWriteToTexture app = new TestWriteToTexture();
|
||||||
@ -84,6 +85,7 @@ public class TestWriteToTexture extends SimpleApplication implements AnalogListe
|
|||||||
guiNode.attachChild(pic);
|
guiNode.attachChild(pic);
|
||||||
|
|
||||||
initCounter = 0;
|
initCounter = 0;
|
||||||
|
gcCounter = 0;
|
||||||
|
|
||||||
flyCam.setEnabled(false);
|
flyCam.setEnabled(false);
|
||||||
inputManager.setCursorVisible(true);
|
inputManager.setCursorVisible(true);
|
||||||
@ -111,6 +113,13 @@ public class TestWriteToTexture extends SimpleApplication implements AnalogListe
|
|||||||
} else {
|
} else {
|
||||||
updateOpenCL(tpf);
|
updateOpenCL(tpf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gcCounter++;
|
||||||
|
if (gcCounter > 10) {
|
||||||
|
Runtime.getRuntime().gc();
|
||||||
|
gcCounter = 0;
|
||||||
|
}
|
||||||
|
// Runtime.getRuntime().runFinalization();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initOpenCL1() {
|
private void initOpenCL1() {
|
||||||
|
@ -45,6 +45,7 @@ public class LwjglBuffer extends Buffer {
|
|||||||
|
|
||||||
public LwjglBuffer(CLMem buffer) {
|
public LwjglBuffer(CLMem buffer) {
|
||||||
this.buffer = buffer;
|
this.buffer = buffer;
|
||||||
|
OpenCLObjectManager.getInstance().registerObject(this);
|
||||||
}
|
}
|
||||||
public CLMem getBuffer() {
|
public CLMem getBuffer() {
|
||||||
return buffer;
|
return buffer;
|
||||||
@ -183,5 +184,44 @@ public class LwjglBuffer extends Buffer {
|
|||||||
long event = Utils.pointerBuffers[0].get(0);
|
long event = Utils.pointerBuffers[0].get(0);
|
||||||
return new LwjglEvent(q.getCLEvent(event));
|
return new LwjglEvent(q.getCLEvent(event));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Event acquireBufferForSharingAsync(CommandQueue queue) {
|
||||||
|
Utils.pointerBuffers[0].rewind();
|
||||||
|
CLCommandQueue q = ((LwjglCommandQueue) queue).getQueue();
|
||||||
|
int ret = CL10GL.clEnqueueAcquireGLObjects(q, buffer, null, Utils.pointerBuffers[0]);
|
||||||
|
Utils.checkError(ret, "clEnqueueAcquireGLObjects");
|
||||||
|
long event = Utils.pointerBuffers[0].get(0);
|
||||||
|
return new LwjglEvent(q.getCLEvent(event));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Event releaseBufferForSharingAsync(CommandQueue queue) {
|
||||||
|
Utils.pointerBuffers[0].rewind();
|
||||||
|
CLCommandQueue q = ((LwjglCommandQueue) queue).getQueue();
|
||||||
|
int ret = CL10GL.clEnqueueReleaseGLObjects(q, buffer, null, Utils.pointerBuffers[0]);
|
||||||
|
Utils.checkError(ret, "clEnqueueReleaseGLObjects");
|
||||||
|
long event = Utils.pointerBuffers[0].get(0);
|
||||||
|
return new LwjglEvent(q.getCLEvent(event));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ObjectReleaser getReleaser() {
|
||||||
|
return new ReleaserImpl(buffer);
|
||||||
|
}
|
||||||
|
private static class ReleaserImpl implements ObjectReleaser {
|
||||||
|
private CLMem mem;
|
||||||
|
private ReleaserImpl(CLMem mem) {
|
||||||
|
this.mem = mem;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void release() {
|
||||||
|
if (mem != null) {
|
||||||
|
int ret = CL10.clReleaseMemObject(mem);
|
||||||
|
mem = null;
|
||||||
|
Utils.reportError(ret, "clReleaseMemObject");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
package com.jme3.opencl.lwjgl;
|
package com.jme3.opencl.lwjgl;
|
||||||
|
|
||||||
import com.jme3.opencl.CommandQueue;
|
import com.jme3.opencl.CommandQueue;
|
||||||
|
import com.jme3.opencl.OpenCLObjectManager;
|
||||||
import org.lwjgl.opencl.CL10;
|
import org.lwjgl.opencl.CL10;
|
||||||
import org.lwjgl.opencl.CLCommandQueue;
|
import org.lwjgl.opencl.CLCommandQueue;
|
||||||
|
|
||||||
@ -45,6 +46,7 @@ public class LwjglCommandQueue implements CommandQueue {
|
|||||||
|
|
||||||
public LwjglCommandQueue(CLCommandQueue queue) {
|
public LwjglCommandQueue(CLCommandQueue queue) {
|
||||||
this.queue = queue;
|
this.queue = queue;
|
||||||
|
OpenCLObjectManager.getInstance().registerObject(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CLCommandQueue getQueue() {
|
public CLCommandQueue getQueue() {
|
||||||
@ -63,4 +65,22 @@ public class LwjglCommandQueue implements CommandQueue {
|
|||||||
Utils.checkError(ret, "clFinish");
|
Utils.checkError(ret, "clFinish");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ObjectReleaser getReleaser() {
|
||||||
|
return new ReleaserImpl(queue);
|
||||||
|
}
|
||||||
|
private static class ReleaserImpl implements ObjectReleaser {
|
||||||
|
private CLCommandQueue queue;
|
||||||
|
private ReleaserImpl(CLCommandQueue queue) {
|
||||||
|
this.queue = queue;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void release() {
|
||||||
|
if (queue != null) {
|
||||||
|
int ret = CL10.clReleaseCommandQueue(queue);
|
||||||
|
queue = null;
|
||||||
|
Utils.reportError(ret, "clReleaseCommandQueue");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,6 @@ import com.jme3.opencl.Context;
|
|||||||
import com.jme3.opencl.Image.ImageDescriptor;
|
import com.jme3.opencl.Image.ImageDescriptor;
|
||||||
import com.jme3.opencl.Image.ImageFormat;
|
import com.jme3.opencl.Image.ImageFormat;
|
||||||
import com.jme3.scene.VertexBuffer;
|
import com.jme3.scene.VertexBuffer;
|
||||||
import com.jme3.scene.mesh.IndexBuffer;
|
|
||||||
import com.jme3.texture.FrameBuffer;
|
import com.jme3.texture.FrameBuffer;
|
||||||
import com.jme3.texture.Texture;
|
import com.jme3.texture.Texture;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
@ -60,6 +59,7 @@ public class LwjglContext extends Context {
|
|||||||
public LwjglContext(CLContext context, List<LwjglDevice> devices) {
|
public LwjglContext(CLContext context, List<LwjglDevice> devices) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.devices = devices;
|
this.devices = devices;
|
||||||
|
OpenCLObjectManager.getInstance().registerObject(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CLContext getContext() {
|
public CLContext getContext() {
|
||||||
@ -207,5 +207,27 @@ public class LwjglContext extends Context {
|
|||||||
Utils.checkError(Utils.errorBuffer, "clCreateProgramWithSource");
|
Utils.checkError(Utils.errorBuffer, "clCreateProgramWithSource");
|
||||||
return new LwjglProgram(p, this);
|
return new LwjglProgram(p, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ObjectReleaser getReleaser() {
|
||||||
|
return new ReleaserImpl(context, devices);
|
||||||
|
}
|
||||||
|
private static class ReleaserImpl implements ObjectReleaser {
|
||||||
|
private CLContext context;
|
||||||
|
private final List<LwjglDevice> devices;
|
||||||
|
private ReleaserImpl(CLContext mem, List<LwjglDevice> devices) {
|
||||||
|
this.context = mem;
|
||||||
|
this.devices = devices;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void release() {
|
||||||
|
if (context != null) {
|
||||||
|
int ret = CL10.clReleaseContext(context);
|
||||||
|
context = null;
|
||||||
|
devices.clear();
|
||||||
|
Utils.reportError(ret, "clReleaseMemObject");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
package com.jme3.opencl.lwjgl;
|
package com.jme3.opencl.lwjgl;
|
||||||
|
|
||||||
import com.jme3.opencl.Event;
|
import com.jme3.opencl.Event;
|
||||||
|
import com.jme3.opencl.OpenCLObjectManager;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import org.lwjgl.opencl.CL10;
|
import org.lwjgl.opencl.CL10;
|
||||||
import org.lwjgl.opencl.CLEvent;
|
import org.lwjgl.opencl.CLEvent;
|
||||||
@ -42,18 +43,29 @@ import org.lwjgl.opencl.CLEvent;
|
|||||||
*/
|
*/
|
||||||
public class LwjglEvent implements Event {
|
public class LwjglEvent implements Event {
|
||||||
private static final Logger LOG = Logger.getLogger(LwjglEvent.class.getName());
|
private static final Logger LOG = Logger.getLogger(LwjglEvent.class.getName());
|
||||||
private final CLEvent event;
|
private CLEvent event;
|
||||||
|
|
||||||
public LwjglEvent(CLEvent event) {
|
public LwjglEvent(CLEvent event) {
|
||||||
this.event = event;
|
this.event = event;
|
||||||
if (event == null) {
|
if (event == null) {
|
||||||
LOG.warning("event is null!");
|
LOG.warning("event is null!");
|
||||||
|
} else {
|
||||||
|
OpenCLObjectManager.getInstance().registerObject(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public CLEvent getEvent() {
|
public CLEvent getEvent() {
|
||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void release() {
|
||||||
|
if (event != null && event.isValid()) {
|
||||||
|
int ret = CL10.clReleaseEvent(event);
|
||||||
|
event = null;
|
||||||
|
Utils.reportError(ret, "clReleaseEvent");
|
||||||
|
LOG.finer("Event deleted");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void waitForFinished() {
|
public void waitForFinished() {
|
||||||
@ -61,6 +73,7 @@ public class LwjglEvent implements Event {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
CL10.clWaitForEvents(event);
|
CL10.clWaitForEvents(event);
|
||||||
|
release(); //short cut to save resources
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -70,6 +83,7 @@ public class LwjglEvent implements Event {
|
|||||||
}
|
}
|
||||||
int status = event.getInfoInt(CL10.CL_EVENT_COMMAND_EXECUTION_STATUS);
|
int status = event.getInfoInt(CL10.CL_EVENT_COMMAND_EXECUTION_STATUS);
|
||||||
if (status == CL10.CL_SUCCESS) {
|
if (status == CL10.CL_SUCCESS) {
|
||||||
|
release(); //short cut to save resources
|
||||||
return true;
|
return true;
|
||||||
} else if (status < 0) {
|
} else if (status < 0) {
|
||||||
Utils.checkError(status, "EventStatus");
|
Utils.checkError(status, "EventStatus");
|
||||||
@ -78,5 +92,28 @@ public class LwjglEvent implements Event {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ObjectReleaser getReleaser() {
|
||||||
|
return new ReleaserImpl(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ReleaserImpl implements ObjectReleaser {
|
||||||
|
private CLEvent event;
|
||||||
|
|
||||||
|
private ReleaserImpl(CLEvent event) {
|
||||||
|
this.event = event;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void release() {
|
||||||
|
if (event != null && event.isValid()) {
|
||||||
|
int ret = CL10.clReleaseEvent(event);
|
||||||
|
event = null;
|
||||||
|
Utils.reportError(ret, "clReleaseEvent");
|
||||||
|
LOG.finer("Event deleted");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,7 @@ public class LwjglImage implements Image {
|
|||||||
|
|
||||||
public LwjglImage(CLMem image) {
|
public LwjglImage(CLMem image) {
|
||||||
this.image = image;
|
this.image = image;
|
||||||
|
OpenCLObjectManager.getInstance().registerObject(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CLMem getImage() {
|
public CLMem getImage() {
|
||||||
@ -542,4 +543,24 @@ public class LwjglImage implements Image {
|
|||||||
long event = Utils.pointerBuffers[0].get(0);
|
long event = Utils.pointerBuffers[0].get(0);
|
||||||
return new LwjglEvent(q.getCLEvent(event));
|
return new LwjglEvent(q.getCLEvent(event));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ObjectReleaser getReleaser() {
|
||||||
|
return new ReleaserImpl(image);
|
||||||
|
}
|
||||||
|
private static class ReleaserImpl implements ObjectReleaser {
|
||||||
|
private CLMem mem;
|
||||||
|
private ReleaserImpl(CLMem mem) {
|
||||||
|
this.mem = mem;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void release() {
|
||||||
|
if (mem != null) {
|
||||||
|
int ret = CL10.clReleaseMemObject(mem);
|
||||||
|
mem = null;
|
||||||
|
Utils.reportError(ret, "clReleaseMemObject");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,6 +52,7 @@ public class LwjglKernel extends Kernel {
|
|||||||
|
|
||||||
public LwjglKernel(CLKernel kernel) {
|
public LwjglKernel(CLKernel kernel) {
|
||||||
this.kernel = kernel;
|
this.kernel = kernel;
|
||||||
|
OpenCLObjectManager.getInstance().registerObject(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CLKernel getKernel() {
|
public CLKernel getKernel() {
|
||||||
@ -215,5 +216,23 @@ public class LwjglKernel extends Kernel {
|
|||||||
Utils.checkError(ret, "clEnqueueNDRangeKernel");
|
Utils.checkError(ret, "clEnqueueNDRangeKernel");
|
||||||
return new LwjglEvent(q.getCLEvent(Utils.pointerBuffers[0].get(0)));
|
return new LwjglEvent(q.getCLEvent(Utils.pointerBuffers[0].get(0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ObjectReleaser getReleaser() {
|
||||||
|
return new ReleaserImpl(kernel);
|
||||||
|
}
|
||||||
|
private static class ReleaserImpl implements ObjectReleaser {
|
||||||
|
private CLKernel kernel;
|
||||||
|
private ReleaserImpl(CLKernel kernel) {
|
||||||
|
this.kernel = kernel;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void release() {
|
||||||
|
if (kernel != null) {
|
||||||
|
int ret = CL10.clReleaseKernel(kernel);
|
||||||
|
kernel = null;
|
||||||
|
Utils.reportError(ret, "clReleaseKernel");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -123,5 +123,5 @@ public final class LwjglPlatform implements Platform {
|
|||||||
public Collection<? extends String> getExtensions() {
|
public Collection<? extends String> getExtensions() {
|
||||||
return Arrays.asList(platform.getInfoString(CL10.CL_PLATFORM_EXTENSIONS).split(" "));
|
return Arrays.asList(platform.getInfoString(CL10.CL_PLATFORM_EXTENSIONS).split(" "));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -33,8 +33,8 @@ package com.jme3.opencl.lwjgl;
|
|||||||
|
|
||||||
import com.jme3.opencl.Kernel;
|
import com.jme3.opencl.Kernel;
|
||||||
import com.jme3.opencl.KernelCompilationException;
|
import com.jme3.opencl.KernelCompilationException;
|
||||||
|
import com.jme3.opencl.OpenCLObjectManager;
|
||||||
import com.jme3.opencl.Program;
|
import com.jme3.opencl.Program;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import org.lwjgl.PointerBuffer;
|
import org.lwjgl.PointerBuffer;
|
||||||
@ -53,6 +53,7 @@ public class LwjglProgram implements Program {
|
|||||||
public LwjglProgram(CLProgram program, LwjglContext context) {
|
public LwjglProgram(CLProgram program, LwjglContext context) {
|
||||||
this.program = program;
|
this.program = program;
|
||||||
this.context = context;
|
this.context = context;
|
||||||
|
OpenCLObjectManager.getInstance().registerObject(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CLProgram getProgram() {
|
public CLProgram getProgram() {
|
||||||
@ -107,5 +108,26 @@ public class LwjglProgram implements Program {
|
|||||||
}
|
}
|
||||||
return kx;
|
return kx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ObjectReleaser getReleaser() {
|
||||||
|
return new ReleaserImpl(program);
|
||||||
|
}
|
||||||
|
private static class ReleaserImpl implements ObjectReleaser {
|
||||||
|
private CLProgram program;
|
||||||
|
private ReleaserImpl(CLProgram program) {
|
||||||
|
this.program = program;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void release() {
|
||||||
|
//LWJGL Bug: releasing a program also released every! kernel associated with that program
|
||||||
|
/*
|
||||||
|
if (program != null) {
|
||||||
|
int ret = CL10.clReleaseProgram(program);
|
||||||
|
program = null;
|
||||||
|
Utils.reportError(ret, "clReleaseProgram");
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,19 +34,32 @@ package com.jme3.opencl.lwjgl;
|
|||||||
import com.jme3.opencl.MappingAccess;
|
import com.jme3.opencl.MappingAccess;
|
||||||
import com.jme3.opencl.MemoryAccess;
|
import com.jme3.opencl.MemoryAccess;
|
||||||
import com.jme3.opencl.OpenCLException;
|
import com.jme3.opencl.OpenCLException;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
import java.nio.*;
|
import java.nio.*;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
import org.lwjgl.BufferUtils;
|
import org.lwjgl.BufferUtils;
|
||||||
import org.lwjgl.LWJGLUtil;
|
import org.lwjgl.LWJGLUtil;
|
||||||
import org.lwjgl.PointerBuffer;
|
import org.lwjgl.PointerBuffer;
|
||||||
import org.lwjgl.opencl.CL10;
|
import org.lwjgl.opencl.*;
|
||||||
import org.lwjgl.opencl.CL12;
|
|
||||||
import org.lwjgl.opencl.Util;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Sebastian Weiss
|
* @author Sebastian Weiss
|
||||||
*/
|
*/
|
||||||
public class Utils {
|
public class Utils {
|
||||||
|
private static final Logger LOG = Logger.getLogger(Utils.class.getName());
|
||||||
|
private Utils() {}
|
||||||
|
|
||||||
|
/** Maps OpenCL error token values to their String representations.
|
||||||
|
Taken directly from org.lwjgl.opencl.Util
|
||||||
|
*/
|
||||||
|
private static final Map<Integer, String> CL_ERROR_TOKENS = LWJGLUtil.getClassTokens(new LWJGLUtil.TokenFilter() {
|
||||||
|
public boolean accept(final Field field, final int value) {
|
||||||
|
return value < 0; // Currently, all OpenCL errors have negative values.
|
||||||
|
}
|
||||||
|
}, null, CL10.class, CL11.class, CL12.class, KHRGLSharing.class, KHRICD.class, APPLEGLSharing.class, EXTDeviceFission.class);
|
||||||
|
|
||||||
public static int getMajorVersion(String version, String prefix) {
|
public static int getMajorVersion(String version, String prefix) {
|
||||||
String s = version.substring(prefix.length());
|
String s = version.substring(prefix.length());
|
||||||
@ -95,8 +108,27 @@ public class Utils {
|
|||||||
checkError(errorBuffer.get(0), callName);
|
checkError(errorBuffer.get(0), callName);
|
||||||
}
|
}
|
||||||
public static void checkError(int error, String callName) {
|
public static void checkError(int error, String callName) {
|
||||||
//TODO: proper handling
|
if (error != CL10.CL_SUCCESS) {
|
||||||
Util.checkCLError(error);
|
String errname = getErrorName(error);
|
||||||
|
if (errname == null) {
|
||||||
|
errname = "UNKNOWN";
|
||||||
|
}
|
||||||
|
throw new OpenCLException("OpenCL error in " + callName + ": " + errname + " (0x" + Integer.toHexString(error) + ")", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void reportError(int error, String callName) {
|
||||||
|
if (error != CL10.CL_SUCCESS) {
|
||||||
|
String errname = getErrorName(error);
|
||||||
|
if (errname == null) {
|
||||||
|
errname = "UNKNOWN";
|
||||||
|
}
|
||||||
|
LOG.log(Level.WARNING, "OpenCL error in {0}: {1} (0x{2})", new Object[]{callName, errname, Integer.toHexString(error)});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getErrorName(int code) {
|
||||||
|
return CL_ERROR_TOKENS.get(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static long getMemoryAccessFlags(MemoryAccess ma) {
|
public static long getMemoryAccessFlags(MemoryAccess ma) {
|
||||||
@ -129,4 +161,5 @@ public class Utils {
|
|||||||
default: throw new IllegalArgumentException("Unknown mapping access: "+ma);
|
default: throw new IllegalArgumentException("Unknown mapping access: "+ma);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user