added memory managing: native resources are now automatically released
This commit is contained in:
parent
0d003275a7
commit
0c47bf18c9
jme3-core/src/main/java/com/jme3
opencl
Buffer.javaCommandQueue.javaContext.javaEvent.javaImage.javaKernel.javaOpenCLObject.javaOpenCLObjectManager.javaProgram.java
renderer/opengl
jme3-examples/src/main/java/jme3test/opencl
jme3-lwjgl/src/main/java/com/jme3/opencl/lwjgl
@ -37,7 +37,7 @@ import java.nio.ByteBuffer;
|
||||
*
|
||||
* @author Sebastian Weiss
|
||||
*/
|
||||
public abstract class Buffer {
|
||||
public abstract class Buffer implements OpenCLObject {
|
||||
|
||||
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 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;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Weiss
|
||||
*/
|
||||
public interface CommandQueue {
|
||||
public interface CommandQueue extends OpenCLObject {
|
||||
|
||||
void flush();
|
||||
|
||||
|
@ -38,7 +38,6 @@ import com.jme3.opencl.Image.ImageDescriptor;
|
||||
import com.jme3.opencl.Image.ImageFormat;
|
||||
import com.jme3.opencl.Image.ImageType;
|
||||
import com.jme3.scene.VertexBuffer;
|
||||
import com.jme3.scene.mesh.IndexBuffer;
|
||||
import com.jme3.texture.FrameBuffer;
|
||||
import com.jme3.texture.Texture;
|
||||
import java.io.BufferedReader;
|
||||
@ -55,7 +54,7 @@ import java.util.logging.Logger;
|
||||
*
|
||||
* @author Sebastian Weiss
|
||||
*/
|
||||
public abstract class Context {
|
||||
public abstract class Context implements OpenCLObject {
|
||||
private static final Logger LOG = Logger.getLogger(Context.class.getName());
|
||||
|
||||
public abstract List<? extends Device> getDevices();
|
||||
|
@ -35,7 +35,7 @@ package com.jme3.opencl;
|
||||
*
|
||||
* @author Sebastian Weiss
|
||||
*/
|
||||
public interface Event {
|
||||
public interface Event extends OpenCLObject {
|
||||
|
||||
void waitForFinished();
|
||||
|
||||
|
@ -39,7 +39,7 @@ import java.util.Objects;
|
||||
*
|
||||
* @author Sebastian Weiss
|
||||
*/
|
||||
public interface Image {
|
||||
public interface Image extends OpenCLObject {
|
||||
|
||||
public static enum ImageChannelType {
|
||||
SNORM_INT8,
|
||||
@ -237,4 +237,5 @@ public interface Image {
|
||||
|
||||
Event acquireImageForSharingAsync(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
|
||||
*/
|
||||
public abstract class Kernel {
|
||||
public abstract class Kernel implements OpenCLObject {
|
||||
protected final WorkSize globalWorkSize;
|
||||
protected final WorkSize workGroupSize;
|
||||
|
||||
@ -180,4 +180,6 @@ public abstract class Kernel {
|
||||
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
|
||||
*/
|
||||
public interface Program {
|
||||
public interface Program extends OpenCLObject {
|
||||
|
||||
void build(String args) 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.TestFunction;
|
||||
import com.jme3.math.*;
|
||||
import com.jme3.opencl.OpenCLObjectManager;
|
||||
import com.jme3.renderer.*;
|
||||
import com.jme3.scene.Mesh;
|
||||
import com.jme3.scene.Mesh.Mode;
|
||||
@ -552,6 +553,7 @@ public final class GLRenderer implements Renderer {
|
||||
public void cleanup() {
|
||||
logger.log(Level.FINE, "Deleting objects and invalidating state");
|
||||
objManager.deleteAllObjects(this);
|
||||
OpenCLObjectManager.getInstance().deleteAllObjects();
|
||||
statistics.clearMemory();
|
||||
invalidateState();
|
||||
}
|
||||
@ -935,6 +937,7 @@ public final class GLRenderer implements Renderer {
|
||||
|
||||
public void postFrame() {
|
||||
objManager.deleteUnused(this);
|
||||
OpenCLObjectManager.getInstance().deleteUnusedObjects();
|
||||
gl.resetStats();
|
||||
}
|
||||
|
||||
|
@ -61,6 +61,7 @@ public class TestWriteToTexture extends SimpleApplication implements AnalogListe
|
||||
private Vector2f C;
|
||||
private Image texCL;
|
||||
private boolean dragging;
|
||||
private int gcCounter;
|
||||
|
||||
public static void main(String[] args){
|
||||
TestWriteToTexture app = new TestWriteToTexture();
|
||||
@ -84,6 +85,7 @@ public class TestWriteToTexture extends SimpleApplication implements AnalogListe
|
||||
guiNode.attachChild(pic);
|
||||
|
||||
initCounter = 0;
|
||||
gcCounter = 0;
|
||||
|
||||
flyCam.setEnabled(false);
|
||||
inputManager.setCursorVisible(true);
|
||||
@ -111,6 +113,13 @@ public class TestWriteToTexture extends SimpleApplication implements AnalogListe
|
||||
} else {
|
||||
updateOpenCL(tpf);
|
||||
}
|
||||
|
||||
gcCounter++;
|
||||
if (gcCounter > 10) {
|
||||
Runtime.getRuntime().gc();
|
||||
gcCounter = 0;
|
||||
}
|
||||
// Runtime.getRuntime().runFinalization();
|
||||
}
|
||||
|
||||
private void initOpenCL1() {
|
||||
|
@ -45,6 +45,7 @@ public class LwjglBuffer extends Buffer {
|
||||
|
||||
public LwjglBuffer(CLMem buffer) {
|
||||
this.buffer = buffer;
|
||||
OpenCLObjectManager.getInstance().registerObject(this);
|
||||
}
|
||||
public CLMem getBuffer() {
|
||||
return buffer;
|
||||
@ -183,5 +184,44 @@ public class LwjglBuffer extends Buffer {
|
||||
long event = Utils.pointerBuffers[0].get(0);
|
||||
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;
|
||||
|
||||
import com.jme3.opencl.CommandQueue;
|
||||
import com.jme3.opencl.OpenCLObjectManager;
|
||||
import org.lwjgl.opencl.CL10;
|
||||
import org.lwjgl.opencl.CLCommandQueue;
|
||||
|
||||
@ -45,6 +46,7 @@ public class LwjglCommandQueue implements CommandQueue {
|
||||
|
||||
public LwjglCommandQueue(CLCommandQueue queue) {
|
||||
this.queue = queue;
|
||||
OpenCLObjectManager.getInstance().registerObject(this);
|
||||
}
|
||||
|
||||
public CLCommandQueue getQueue() {
|
||||
@ -63,4 +65,22 @@ public class LwjglCommandQueue implements CommandQueue {
|
||||
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.ImageFormat;
|
||||
import com.jme3.scene.VertexBuffer;
|
||||
import com.jme3.scene.mesh.IndexBuffer;
|
||||
import com.jme3.texture.FrameBuffer;
|
||||
import com.jme3.texture.Texture;
|
||||
import java.nio.ByteBuffer;
|
||||
@ -60,6 +59,7 @@ public class LwjglContext extends Context {
|
||||
public LwjglContext(CLContext context, List<LwjglDevice> devices) {
|
||||
this.context = context;
|
||||
this.devices = devices;
|
||||
OpenCLObjectManager.getInstance().registerObject(this);
|
||||
}
|
||||
|
||||
public CLContext getContext() {
|
||||
@ -207,5 +207,27 @@ public class LwjglContext extends Context {
|
||||
Utils.checkError(Utils.errorBuffer, "clCreateProgramWithSource");
|
||||
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;
|
||||
|
||||
import com.jme3.opencl.Event;
|
||||
import com.jme3.opencl.OpenCLObjectManager;
|
||||
import java.util.logging.Logger;
|
||||
import org.lwjgl.opencl.CL10;
|
||||
import org.lwjgl.opencl.CLEvent;
|
||||
@ -42,18 +43,29 @@ import org.lwjgl.opencl.CLEvent;
|
||||
*/
|
||||
public class LwjglEvent implements Event {
|
||||
private static final Logger LOG = Logger.getLogger(LwjglEvent.class.getName());
|
||||
private final CLEvent event;
|
||||
private CLEvent event;
|
||||
|
||||
public LwjglEvent(CLEvent event) {
|
||||
this.event = event;
|
||||
if (event == null) {
|
||||
LOG.warning("event is null!");
|
||||
} else {
|
||||
OpenCLObjectManager.getInstance().registerObject(this);
|
||||
}
|
||||
}
|
||||
|
||||
public CLEvent getEvent() {
|
||||
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
|
||||
public void waitForFinished() {
|
||||
@ -61,6 +73,7 @@ public class LwjglEvent implements Event {
|
||||
return;
|
||||
}
|
||||
CL10.clWaitForEvents(event);
|
||||
release(); //short cut to save resources
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -70,6 +83,7 @@ public class LwjglEvent implements Event {
|
||||
}
|
||||
int status = event.getInfoInt(CL10.CL_EVENT_COMMAND_EXECUTION_STATUS);
|
||||
if (status == CL10.CL_SUCCESS) {
|
||||
release(); //short cut to save resources
|
||||
return true;
|
||||
} else if (status < 0) {
|
||||
Utils.checkError(status, "EventStatus");
|
||||
@ -78,5 +92,28 @@ public class LwjglEvent implements Event {
|
||||
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) {
|
||||
this.image = image;
|
||||
OpenCLObjectManager.getInstance().registerObject(this);
|
||||
}
|
||||
|
||||
public CLMem getImage() {
|
||||
@ -542,4 +543,24 @@ public class LwjglImage implements Image {
|
||||
long event = Utils.pointerBuffers[0].get(0);
|
||||
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) {
|
||||
this.kernel = kernel;
|
||||
OpenCLObjectManager.getInstance().registerObject(this);
|
||||
}
|
||||
|
||||
public CLKernel getKernel() {
|
||||
@ -215,5 +216,23 @@ public class LwjglKernel extends Kernel {
|
||||
Utils.checkError(ret, "clEnqueueNDRangeKernel");
|
||||
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() {
|
||||
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.KernelCompilationException;
|
||||
import com.jme3.opencl.OpenCLObjectManager;
|
||||
import com.jme3.opencl.Program;
|
||||
import java.util.ArrayList;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import org.lwjgl.PointerBuffer;
|
||||
@ -53,6 +53,7 @@ public class LwjglProgram implements Program {
|
||||
public LwjglProgram(CLProgram program, LwjglContext context) {
|
||||
this.program = program;
|
||||
this.context = context;
|
||||
OpenCLObjectManager.getInstance().registerObject(this);
|
||||
}
|
||||
|
||||
public CLProgram getProgram() {
|
||||
@ -107,5 +108,26 @@ public class LwjglProgram implements Program {
|
||||
}
|
||||
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.MemoryAccess;
|
||||
import com.jme3.opencl.OpenCLException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.*;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.LWJGLUtil;
|
||||
import org.lwjgl.PointerBuffer;
|
||||
import org.lwjgl.opencl.CL10;
|
||||
import org.lwjgl.opencl.CL12;
|
||||
import org.lwjgl.opencl.Util;
|
||||
import org.lwjgl.opencl.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Weiss
|
||||
*/
|
||||
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) {
|
||||
String s = version.substring(prefix.length());
|
||||
@ -95,8 +108,27 @@ public class Utils {
|
||||
checkError(errorBuffer.get(0), callName);
|
||||
}
|
||||
public static void checkError(int error, String callName) {
|
||||
//TODO: proper handling
|
||||
Util.checkCLError(error);
|
||||
if (error != CL10.CL_SUCCESS) {
|
||||
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) {
|
||||
@ -129,4 +161,5 @@ public class Utils {
|
||||
default: throw new IllegalArgumentException("Unknown mapping access: "+ma);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user