reworked releasing system.

Now one has to either release a native OpenCLObject manually with release() or register it for automatic garbage collection using register().
These changes greatly improve the performance by reducing the load on the OpenCLObjectManager.
This commit is contained in:
shamanDevel 2016-05-02 08:30:00 +02:00
parent a26e526945
commit 4be6013068
27 changed files with 230 additions and 155 deletions

View File

@ -0,0 +1,62 @@
/*
* 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;
/**
* Abstract implementation of {@link OpenCLObject} providing the release
* mechanisms.
* @author Sebastian Weiss
*/
public abstract class AbstractOpenCLObject implements OpenCLObject {
protected final ObjectReleaser releaser;
protected AbstractOpenCLObject(ObjectReleaser releaser) {
this.releaser = releaser;
}
@Override
public void register() {
OpenCLObjectManager.getInstance().registerObject(this);
}
@Override
public void release() {
releaser.release();
}
@Override
@SuppressWarnings("FinalizeDeclaration")
protected void finalize() throws Throwable {
release();
}
@Override
public ObjectReleaser getReleaser() {
return releaser;
}
}

View File

@ -47,8 +47,12 @@ import java.nio.ByteBuffer;
* @see Context#createBuffer(long, com.jme3.opencl.MemoryAccess)
* @author shaman
*/
public abstract class Buffer implements OpenCLObject {
public abstract class Buffer extends AbstractOpenCLObject {
protected Buffer(ObjectReleaser releaser) {
super(releaser);
}
/**
* @return the size of the buffer in bytes.
* @see Context#createBuffer(long)

View File

@ -42,8 +42,12 @@ package com.jme3.opencl;
* and all commands are sent to this device.
* @author shaman
*/
public interface CommandQueue extends OpenCLObject {
public abstract class CommandQueue extends AbstractOpenCLObject {
protected CommandQueue(ObjectReleaser releaser) {
super(releaser);
}
/**
* Issues all previously queued OpenCL commands in command_queue to the
* device associated with command queue. Flush only guarantees that all
@ -51,7 +55,7 @@ public interface CommandQueue extends OpenCLObject {
* appropriate device. There is no guarantee that they will be complete
* after flush returns.
*/
void flush();
public abstract void flush();
/**
* Blocks until all previously queued OpenCL commands in command queue are
@ -59,6 +63,6 @@ public interface CommandQueue extends OpenCLObject {
* return until all previously queued commands in command queue have been
* processed and completed. Finish is also a synchronization point.
*/
void finish();
public abstract void finish();
}

View File

@ -63,9 +63,13 @@ import java.util.logging.Logger;
* </ul>
* @author shaman
*/
public abstract class Context implements OpenCLObject {
public abstract class Context extends AbstractOpenCLObject {
private static final Logger LOG = Logger.getLogger(Context.class.getName());
protected Context(ObjectReleaser releaser) {
super(releaser);
}
/**
* Returns all available devices for this context.
* These devices all belong to the same {@link Platform}.

View File

@ -38,16 +38,22 @@ package com.jme3.opencl;
* is done.
* @author shaman
*/
public interface Event extends OpenCLObject {
public abstract class Event extends AbstractOpenCLObject {
protected Event(ObjectReleaser releaser) {
super(releaser);
}
/**
* Waits until the action has finished (blocking)
* Waits until the action has finished (blocking).
* This automatically releases the event.
*/
void waitForFinished();
public abstract void waitForFinished();
/**
* Tests if the action is completed
* Tests if the action is completed.
* If the action is completed, the event is released.
* @return {@code true} if the action is completed
*/
boolean isCompleted();
public abstract boolean isCompleted();
}

View File

@ -74,7 +74,7 @@ import java.util.Objects;
*
* @author shaman
*/
public interface Image extends OpenCLObject {
public abstract class Image extends AbstractOpenCLObject {
/**
* {@code ImageChannelType} describes the size of the channel data type.
@ -245,47 +245,51 @@ memory layout in which channels are stored in the image.
}
}
protected Image(ObjectReleaser releaser) {
super(releaser);
}
/**
* @return the width of the image
*/
long getWidth();
public abstract long getWidth();
/**
* @return the height of the image
*/
long getHeight();
public abstract long getHeight();
/**
* @return the depth of the image
*/
long getDepth();
public abstract long getDepth();
/**
* @return the row pitch when the image was created from a host buffer
* @see ImageDescriptor#ImageDescriptor(com.jme3.opencl.Image.ImageType, long, long, long, long, long, long, java.nio.ByteBuffer)
*/
long getRowPitch();
public abstract long getRowPitch();
/**
* @return the slice pitch when the image was created from a host buffer
* @see ImageDescriptor#ImageDescriptor(com.jme3.opencl.Image.ImageType, long, long, long, long, long, long, java.nio.ByteBuffer)
*/
long getSlicePitch();
public abstract long getSlicePitch();
/**
* @return the number of elements in the image array
* @see ImageType#IMAGE_1D_ARRAY
* @see ImageType#IMAGE_2D_ARRAY
*/
long getArraySize();
public abstract long getArraySize();
/**
* @return the image format
*/
ImageFormat getImageFormat();
public abstract ImageFormat getImageFormat();
/**
* @return the image type
*/
ImageType getImageType();
public abstract ImageType getImageType();
/**
* @return the number of bytes per pixel
*/
int getElementSize();
public abstract int getElementSize();
/**
* Performs a blocking read of the image into the specified byte buffer.
@ -298,7 +302,7 @@ memory layout in which channels are stored in the image.
* @param slicePitch the slice pitch of the target buffer, must be set to 0 for 1D and 2D images.
* If set to 0 for 3D images, the slice pitch is calculated as {@code rowPitch * height}
*/
void readImage(CommandQueue queue, ByteBuffer dest, long[] origin, long[] region, long rowPitch, long slicePitch);
public abstract void readImage(CommandQueue queue, ByteBuffer dest, long[] origin, long[] region, long rowPitch, long slicePitch);
/**
* Performs an async/non-blocking read of the image into the specified byte buffer.
* @param queue the command queue
@ -311,7 +315,7 @@ memory layout in which channels are stored in the image.
* If set to 0 for 3D images, the slice pitch is calculated as {@code rowPitch * height}
* @return the event object indicating the status of the operation
*/
Event readImageAsync(CommandQueue queue, ByteBuffer dest, long[] origin, long[] region, long rowPitch, long slicePitch);
public abstract Event readImageAsync(CommandQueue queue, ByteBuffer dest, long[] origin, long[] region, long rowPitch, long slicePitch);
/**
* Performs a blocking write from the specified byte buffer into the image.
@ -324,7 +328,7 @@ memory layout in which channels are stored in the image.
* @param slicePitch the slice pitch of the target buffer, must be set to 0 for 1D and 2D images.
* If set to 0 for 3D images, the slice pitch is calculated as {@code rowPitch * height}
*/
void writeImage(CommandQueue queue, ByteBuffer src, long[] origin, long[] region, long rowPitch, long slicePitch);
public abstract void writeImage(CommandQueue queue, ByteBuffer src, long[] origin, long[] region, long rowPitch, long slicePitch);
/**
* Performs an async/non-blocking write from the specified byte buffer into the image.
* @param queue the command queue
@ -337,7 +341,7 @@ memory layout in which channels are stored in the image.
* If set to 0 for 3D images, the slice pitch is calculated as {@code rowPitch * height}
* @return the event object indicating the status of the operation
*/
Event writeImageAsync(CommandQueue queue, ByteBuffer src, long[] origin, long[] region, long rowPitch, long slicePitch);
public abstract Event writeImageAsync(CommandQueue queue, ByteBuffer src, long[] origin, long[] region, long rowPitch, long slicePitch);
/**
* Performs a blocking copy operation from one image to another.
@ -348,7 +352,7 @@ memory layout in which channels are stored in the image.
* @param destOrigin the target image origin, see class description for the format
* @param region the copied region, see class description for the format
*/
void copyTo(CommandQueue queue, Image dest, long[] srcOrigin, long[] destOrigin, long[] region);
public abstract void copyTo(CommandQueue queue, Image dest, long[] srcOrigin, long[] destOrigin, long[] region);
/**
* Performs an async/non-blocking copy operation from one image to another.
* <b>Important:</b> Both images must have the same format!
@ -359,7 +363,7 @@ memory layout in which channels are stored in the image.
* @param region the copied region, see class description for the format
* @return the event object indicating the status of the operation
*/
Event copyToAsync(CommandQueue queue, Image dest, long[] srcOrigin, long[] destOrigin, long[] region);
public abstract Event copyToAsync(CommandQueue queue, Image dest, long[] srcOrigin, long[] destOrigin, long[] region);
/**
* Maps the image into host memory.
@ -373,7 +377,7 @@ memory layout in which channels are stored in the image.
* @return a structure describing the mapped memory
* @see #unmap(com.jme3.opencl.CommandQueue, com.jme3.opencl.Image.ImageMapping)
*/
ImageMapping map(CommandQueue queue, long[] origin, long[] region, MappingAccess access);
public abstract ImageMapping map(CommandQueue queue, long[] origin, long[] region, MappingAccess access);
/**
* Non-blocking version of {@link #map(com.jme3.opencl.CommandQueue, long[], long[], com.jme3.opencl.MappingAccess) }.
* The returned structure contains the mapped byte buffer and row and slice pitch.
@ -385,13 +389,13 @@ memory layout in which channels are stored in the image.
* @return a structure describing the mapped memory
* @see #unmap(com.jme3.opencl.CommandQueue, com.jme3.opencl.Image.ImageMapping)
*/
ImageMapping mapAsync(CommandQueue queue, long[] origin, long[] region, MappingAccess access);
public abstract ImageMapping mapAsync(CommandQueue queue, long[] origin, long[] region, MappingAccess access);
/**
* Unmaps the mapped memory
* @param queue the command queue
* @param mapping the mapped memory
*/
void unmap(CommandQueue queue, ImageMapping mapping);
public abstract void unmap(CommandQueue queue, ImageMapping mapping);
/**
* Describes a mapped region of the image
@ -442,7 +446,7 @@ memory layout in which channels are stored in the image.
* @param color the color to fill
* @return an event object to detect for the completion
*/
Event fillAsync(CommandQueue queue, long[] origin, long[] region, ColorRGBA color);
public abstract Event fillAsync(CommandQueue queue, long[] origin, long[] region, ColorRGBA color);
/**
* Fills the image with the specified color given as four integer variables.
* Does <b>not</b> work if the image channel is {@link ImageChannelType#FLOAT}
@ -453,7 +457,7 @@ memory layout in which channels are stored in the image.
* @param color the color to fill, must be an array of length 4
* @return an event object to detect for the completion
*/
Event fillAsync(CommandQueue queue, long[] origin, long[] region, int[] color);
public abstract Event fillAsync(CommandQueue queue, long[] origin, long[] region, int[] color);
/**
* Copies this image into the specified buffer, no format conversion is done.
@ -466,7 +470,7 @@ memory layout in which channels are stored in the image.
* @param destOffset an offset into the target buffer
* @return the event object to detect the completion of the operation
*/
Event copyToBufferAsync(CommandQueue queue, Buffer dest, long[] srcOrigin, long[] srcRegion, long destOffset);
public abstract Event copyToBufferAsync(CommandQueue queue, Buffer dest, long[] srcOrigin, long[] srcRegion, long destOffset);
/**
* Aquires this image object for using. Only call this method if this image
@ -480,7 +484,7 @@ memory layout in which channels are stored in the image.
* @param queue the command queue
* @return the event object
*/
Event acquireImageForSharingAsync(CommandQueue queue);
public abstract Event acquireImageForSharingAsync(CommandQueue queue);
/**
* Releases a shared image object.
* Call this method after the image object was acquired by
@ -489,7 +493,7 @@ memory layout in which channels are stored in the image.
* @param queue the command queue
* @return the event object
*/
Event releaseImageForSharingAsync(CommandQueue queue);
public abstract Event releaseImageForSharingAsync(CommandQueue queue);
//TODO: add variants of the above two methods that don't create the event object, but release the event immediately
}

View File

@ -82,7 +82,7 @@ import java.util.Arrays;
* @author shaman
* @see Program#createKernel(java.lang.String)
*/
public abstract class Kernel implements OpenCLObject {
public abstract class Kernel extends AbstractOpenCLObject {
/**
* The current global work size
*/
@ -92,7 +92,8 @@ public abstract class Kernel implements OpenCLObject {
*/
protected final WorkSize workGroupSize;
protected Kernel() {
protected Kernel(ObjectReleaser releaser) {
super(releaser);
this.globalWorkSize = new WorkSize(0);
this.workGroupSize = new WorkSize(0);
}

View File

@ -32,14 +32,44 @@
package com.jme3.opencl;
/**
*
* Base interface of all native OpenCL objects.
* This interface provides the functionality for savely release the object.
* @author shaman
*/
public interface OpenCLObject {
/**
* Releaser for an {@link OpenCLObject}.
* Implementations of this interface must not hold a reference to the
* {@code OpenCLObject} directly.
*/
public static interface ObjectReleaser {
/**
* Releases the native resources of the associated {@link OpenCLObject}.
* This method must be guarded against multiple calls: only the first
* call should release, the next ones must not throw an exception.
*/
void release();
}
/**
* Returns the releaser object. Multiple calls should return the same object.
* The ObjectReleaser is used to release the OpenCLObject when it is garbage
* collected. Therefore, the returned object must not hold a reference to
* the OpenCLObject.
* @return the object releaser
*/
ObjectReleaser getReleaser();
/**
* Releases this native object.
* Should delegate to {@code getReleaser().release()}.
*/
void release();
/**
* Registers this object for automatic releasing on garbage collection.
* By default, OpenCLObjects are not registered in the
* {@link OpenCLObjectManager}, you have to release it manually
* by calling {@link #release() }.
* Without registering or releasing, a memory leak might occur.
*/
void register();
}

View File

@ -43,8 +43,8 @@ import java.util.logging.Logger;
*/
public class OpenCLObjectManager {
private static final Logger LOG = Logger.getLogger(OpenCLObjectManager.class.getName());
private static final Level LOG_LEVEL1 = Level.FINER;
private static final Level LOG_LEVEL2 = Level.FINE;
private static final Level LOG_LEVEL1 = Level.INFO;
private static final Level LOG_LEVEL2 = Level.INFO;
/**
* Call Runtime.getRuntime().gc() every these frames
*/
@ -85,6 +85,7 @@ public class OpenCLObjectManager {
public void deleteUnusedObjects() {
if (activeObjects.isEmpty()) {
LOG.log(LOG_LEVEL2, "no active natives");
return; //nothing to do
}
@ -108,7 +109,7 @@ public class OpenCLObjectManager {
removed++;
}
if (removed >= 1) {
LOG.log(LOG_LEVEL2, "NativeObjectManager: {0} native objects were removed from native", removed);
LOG.log(LOG_LEVEL2, "{0} native objects were removed from native", removed);
}
}

View File

@ -42,8 +42,12 @@ package com.jme3.opencl;
* @see #createKernel(java.lang.String)
* @author shaman
*/
public interface Program extends OpenCLObject {
public abstract class Program extends AbstractOpenCLObject {
protected Program(ObjectReleaser releaser) {
super(releaser);
}
/**
* Builds this program with the specified argument string.
* Please see the official OpenCL specification for a definition of
@ -52,13 +56,15 @@ public interface Program extends OpenCLObject {
* @throws KernelCompilationException if the compilation fails
* @see #build()
*/
void build(String args) throws KernelCompilationException;
public abstract void build(String args) throws KernelCompilationException;
/**
* Builds this program without additional arguments
* @throws KernelCompilationException if the compilation fails
* @see #build(java.lang.String)
*/
void build() throws KernelCompilationException;
public void build() throws KernelCompilationException {
build("");
}
/**
* Creates the kernel with the specified name.
@ -67,13 +73,13 @@ public interface Program extends OpenCLObject {
* @throws OpenCLException if the kernel was not found or some other
* error occured
*/
Kernel createKernel(String name);
public abstract Kernel createKernel(String name);
/**
* Creates all available kernels in this program.
* The names of the kernels can then by queried by {@link Kernel#getName() }.
* @return an array of all kernels
*/
Kernel[] createAllKernels();
public abstract Kernel[] createAllKernels();
}

View File

@ -85,6 +85,8 @@ public class HelloOpenCL extends SimpleApplication {
str.append("\n Kernel: ").append(testKernel(clContext, clQueue));
str.append("\n Images: ").append(testImages(clContext, clQueue));
clQueue.release();
BitmapText txt1 = new BitmapText(fnt);
txt1.setText(str.toString());
txt1.setLocalTranslation(5, settings.getHeight() - 5, 0);
@ -159,6 +161,10 @@ public class HelloOpenCL extends SimpleApplication {
assertEquals((byte) (i+low), b, "Wrong byte read");
}
//release
b1.release();
b2.release();
} catch (AssertionError ex) {
LOG.log(Level.SEVERE, "Buffer test failed with an assertion error");
return false;
@ -193,6 +199,11 @@ public class HelloOpenCL extends SimpleApplication {
assertEquals(value, v, "Buffer filled with the wrong value at index "+i);
}
buffer.unmap(clQueue, buf);
//release
buffer.release();
kernel.release();
program.release();
} catch (AssertionError ex) {
LOG.log(Level.SEVERE, "kernel test failed with an assertion error");
@ -239,7 +250,8 @@ public class HelloOpenCL extends SimpleApplication {
//copy to a buffer
Buffer buffer = clContext.createBuffer(4*4*500*1024);
image.copyToBufferAsync(clQueue, buffer, new long[]{10,10,0}, new long[]{500,1024,1}, 0);
Event e3 = image.copyToBufferAsync(clQueue, buffer, new long[]{10,10,0}, new long[]{500,1024,1}, 0);
e3.release();
//this buffer must be completely red
ByteBuffer map1 = buffer.map(clQueue, MappingAccess.MAP_READ_ONLY);
FloatBuffer map1F = map1.asFloatBuffer(); map1F.rewind();
@ -282,6 +294,11 @@ public class HelloOpenCL extends SimpleApplication {
}
image2.unmap(clQueue, map2);
//release
image.release();
image2.release();
buffer.release();
} catch (AssertionError ex) {
LOG.log(Level.SEVERE, "image test failed with an assertion error");
return false;

View File

@ -107,6 +107,7 @@ public class TestVertexBufferSharing extends SimpleApplication {
private void initOpenCL1() {
clContext = context.getOpenCLContext();
clQueue = clContext.createQueue();
clQueue.register();
//create kernel
String source = ""
+ "__kernel void ScaleKernel(__global float* vb, float scale)\n"
@ -118,12 +119,15 @@ public class TestVertexBufferSharing extends SimpleApplication {
+ "}\n";
Program program = clContext.createProgramFromSourceCode(source);
program.build();
program.register();
kernel = program.createKernel("ScaleKernel");
kernel.register();
}
private void initOpenCL2() {
//bind vertex buffer to OpenCL
VertexBuffer vb = geom.getMesh().getBuffer(VertexBuffer.Type.Position);
buffer = clContext.bindVertexBuffer(vb, MemoryAccess.READ_WRITE);
buffer.register();
ws = new com.jme3.opencl.Kernel.WorkSize(geom.getMesh().getVertexCount());
}
private void updateOpenCL(float tpf) {
@ -131,15 +135,15 @@ public class TestVertexBufferSharing extends SimpleApplication {
time += tpf;
//aquire resource
buffer.acquireBufferForSharingAsync(clQueue);
buffer.acquireBufferForSharingAsync(clQueue).release();
//no need to wait for the returned event, since the kernel implicitely waits for it (same command queue)
//execute kernel
float scale = (float) Math.pow(1.1, (1.0 - time%2) / 16.0);
kernel.Run1(clQueue, ws, buffer, scale);
kernel.Run1(clQueue, ws, buffer, scale).release();
//release resource
buffer.releaseBufferForSharingAsync(clQueue);
buffer.releaseBufferForSharingAsync(clQueue).release();
}
}

View File

@ -120,26 +120,31 @@ public class TestWriteToTexture extends SimpleApplication implements AnalogListe
private void initOpenCL1() {
clContext = context.getOpenCLContext();
clQueue = clContext.createQueue();
clQueue.register();
//create kernel
Program program = clContext.createProgramFromSourceFiles(assetManager, "jme3test/opencl/JuliaSet.cl");
program.build();
program.register();
kernel = program.createKernel("JuliaSet");
kernel.register();
C = new Vector2f(0.12f, -0.2f);
}
private void initOpenCL2() {
//bind image to OpenCL
texCL = clContext.bindImage(tex, MemoryAccess.WRITE_ONLY);
texCL.register();
}
private void updateOpenCL(float tpf) {
//aquire resource
texCL.acquireImageForSharingAsync(clQueue);
texCL.acquireImageForSharingAsync(clQueue).release();
//no need to wait for the returned event, since the kernel implicitely waits for it (same command queue)
//execute kernel
kernel.Run1(clQueue, new com.jme3.opencl.Kernel.WorkSize(settings.getWidth(), settings.getHeight()), texCL, C, 16);
kernel.Run1(clQueue, new com.jme3.opencl.Kernel.WorkSize(settings.getWidth(), settings.getHeight()), texCL, C, 16)
.release();
//release resource
texCL.releaseImageForSharingAsync(clQueue);
texCL.releaseImageForSharingAsync(clQueue).release();
}
@Override

View File

@ -48,9 +48,9 @@ public class JoclBuffer extends Buffer {
final CL cl;
public JoclBuffer(long id) {
super(new ReleaserImpl(id));
this.id = id;
this.cl = CLPlatform.getLowLevelCLInterface();
OpenCLObjectManager.getInstance().registerObject(this);
}
@Override
@ -203,10 +203,6 @@ public class JoclBuffer extends Buffer {
return new JoclEvent(event);
}
@Override
public ObjectReleaser getReleaser() {
return new ReleaserImpl(id);
}
private static class ReleaserImpl implements ObjectReleaser {
private long mem;
private ReleaserImpl(long mem) {

View File

@ -42,15 +42,15 @@ import com.jogamp.opencl.llb.CLCommandQueueBinding;
*
* @author shaman
*/
public class JoclCommandQueue implements CommandQueue {
public class JoclCommandQueue extends CommandQueue {
final CL cl;
final long id;
public JoclCommandQueue(long id) {
super(new ReleaserImpl(id));
this.id = id;
this.cl = CLPlatform.getLowLevelCLInterface();
OpenCLObjectManager.getInstance().registerObject(this);
}
@Override
@ -65,23 +65,17 @@ public class JoclCommandQueue implements CommandQueue {
Utils.checkError(ret, "clFinish");
}
@Override
public ObjectReleaser getReleaser() {
return new ReleaserImpl(id, cl);
}
private static class ReleaserImpl implements ObjectReleaser {
private long id;
private CLCommandQueueBinding cl;
private ReleaserImpl(long id, CLCommandQueueBinding cl) {
private ReleaserImpl(long id) {
this.id = id;
this.cl = cl;
}
@Override
public void release() {
if (id != 0) {
int ret = cl.clReleaseCommandQueue(id);
int ret = CLPlatform.getLowLevelCLInterface().clReleaseCommandQueue(id);
id = 0;
Utils.reportError(ret, "clReleaseCommandQueue");
}

View File

@ -40,7 +40,6 @@ import com.jme3.texture.FrameBuffer;
import com.jme3.texture.Texture;
import com.jogamp.opencl.CLContext;
import com.jogamp.opencl.CLImageFormat;
import com.jogamp.opencl.CLMemory;
import com.jogamp.opencl.CLMemory.Mem;
import com.jogamp.opencl.CLPlatform;
import com.jogamp.opencl.llb.CL;
@ -48,7 +47,6 @@ import com.jogamp.opencl.llb.gl.CLGL;
import com.jogamp.opencl.llb.impl.CLImageFormatImpl;
import com.jogamp.opengl.GL;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
@ -66,11 +64,11 @@ public class JoclContext extends Context {
private final List<JoclDevice> devices;
public JoclContext(CLContext context, List<JoclDevice> devices) {
super(new ReleaserImpl(context.ID, devices));
this.context = context;
this.id = context.ID;
this.cl = context.getCL();
this.devices = devices;
OpenCLObjectManager.getInstance().registerObject(this);
}
public CLContext getContext() {
@ -224,10 +222,6 @@ public class JoclContext extends Context {
return new JoclProgram(p, this);
}
@Override
public ObjectReleaser getReleaser() {
return new ReleaserImpl(id, devices);
}
private static class ReleaserImpl implements ObjectReleaser {
private long id;
private final List<JoclDevice> devices;

View File

@ -41,16 +41,16 @@ import java.util.logging.Logger;
*
* @author shaman
*/
public class JoclEvent implements Event {
public class JoclEvent extends Event {
private static final Logger LOG = Logger.getLogger(JoclEvent.class.getName());
final long id;
final CL cl;
public JoclEvent(long id) {
super(new ReleaserImpl(id));
this.id = id;
this.cl = CLPlatform.getLowLevelCLInterface();
OpenCLObjectManager.getInstance().registerObject(this);
}
@Override
@ -59,6 +59,7 @@ public class JoclEvent implements Event {
Utils.pointers[0].put(0, id);
int ret = cl.clWaitForEvents(1, Utils.pointers[0]);
Utils.checkError(ret, "clWaitForEvents");
release();
}
@Override
@ -68,6 +69,7 @@ public class JoclEvent implements Event {
Utils.checkError(err, "clGetEventInfo");
int status = Utils.tempBuffers[0].b16i.get(0);
if (status == CL.CL_SUCCESS) {
release();
return true;
} else if (status < 0) {
Utils.checkError(status, "EventStatus");
@ -76,11 +78,6 @@ public class JoclEvent implements Event {
return false;
}
}
@Override
public ObjectReleaser getReleaser() {
return new ReleaserImpl(id);
}
private static class ReleaserImpl implements ObjectReleaser {
private long event;

View File

@ -44,16 +44,16 @@ import java.util.logging.Logger;
*
* @author shaman
*/
public class JoclImage implements Image {
public class JoclImage extends Image {
private static final Logger LOG = Logger.getLogger(JoclImage.class.getName());
final long id;
final CL cl;
public JoclImage(long image) {
super(new ReleaserImpl(image));
this.id = image;
this.cl = CLPlatform.getLowLevelCLInterface();
OpenCLObjectManager.getInstance().registerObject(this);
}
public static int decodeImageChannelOrder(ImageChannelOrder order) {
@ -512,10 +512,6 @@ public class JoclImage implements Image {
return new JoclEvent(event);
}
@Override
public ObjectReleaser getReleaser() {
return new ReleaserImpl(id);
}
private static class ReleaserImpl implements ObjectReleaser {
private long mem;
private ReleaserImpl(long mem) {

View File

@ -37,7 +37,6 @@ import com.jme3.math.Vector4f;
import com.jme3.opencl.*;
import com.jme3.opencl.Buffer;
import com.jogamp.common.nio.PointerBuffer;
import com.jogamp.opencl.CLKernel;
import com.jogamp.opencl.CLPlatform;
import com.jogamp.opencl.llb.CL;
import java.nio.*;
@ -55,6 +54,7 @@ public class JoclKernel extends Kernel {
final CL cl;
public JoclKernel(long kernel) {
super(new ReleaserImpl(kernel));
this.kernel = kernel;
this.cl = CLPlatform.getLowLevelCLInterface();
OpenCLObjectManager.getInstance().registerObject(this);
@ -240,10 +240,6 @@ public class JoclKernel extends Kernel {
return new JoclEvent(Utils.pointers[0].get(0));
}
@Override
public ObjectReleaser getReleaser() {
return new ReleaserImpl(kernel);
}
private static class ReleaserImpl implements ObjectReleaser {
private long kernel;
private ReleaserImpl(long kernel) {

View File

@ -50,7 +50,7 @@ import static com.jogamp.opencl.llb.CL.CL_SUCCESS;
*
* @author shaman
*/
public class JoclProgram implements Program {
public class JoclProgram extends Program {
private static final Logger LOG = Logger.getLogger(JoclProgram.class.getName());
final long program;
@ -58,10 +58,10 @@ public class JoclProgram implements Program {
private final JoclContext context;
public JoclProgram(long program, JoclContext context) {
super(new ReleaserImpl(program));
this.program = program;
this.context = context;
this.cl = CLPlatform.getLowLevelCLInterface();
OpenCLObjectManager.getInstance().registerObject(this);
}
@Override
@ -79,11 +79,6 @@ public class JoclProgram implements Program {
LOG.log(Level.INFO, "Program compiled:\n{0}", Log());
}
}
@Override
public void build() throws KernelCompilationException {
build("");
}
private String Log(long device) {
Utils.pointers[0].rewind();
@ -131,10 +126,6 @@ public class JoclProgram implements Program {
return kx;
}
@Override
public ObjectReleaser getReleaser() {
return new ReleaserImpl(program);
}
private static class ReleaserImpl implements ObjectReleaser {
private long program;
private ReleaserImpl(long program) {

View File

@ -44,8 +44,8 @@ public class LwjglBuffer extends Buffer {
private final CLMem buffer;
public LwjglBuffer(CLMem buffer) {
super(new ReleaserImpl(buffer));
this.buffer = buffer;
OpenCLObjectManager.getInstance().registerObject(this);
}
public CLMem getBuffer() {
return buffer;
@ -205,10 +205,6 @@ public class LwjglBuffer extends Buffer {
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) {

View File

@ -40,13 +40,13 @@ import org.lwjgl.opencl.CLCommandQueue;
*
* @author shaman
*/
public class LwjglCommandQueue implements CommandQueue {
public class LwjglCommandQueue extends CommandQueue {
private final CLCommandQueue queue;
public LwjglCommandQueue(CLCommandQueue queue) {
super(new ReleaserImpl(queue));
this.queue = queue;
OpenCLObjectManager.getInstance().registerObject(this);
}
public CLCommandQueue getQueue() {
@ -65,10 +65,6 @@ 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) {

View File

@ -57,9 +57,9 @@ public class LwjglContext extends Context {
private final List<LwjglDevice> devices;
public LwjglContext(CLContext context, List<LwjglDevice> devices) {
super(new ReleaserImpl(context, devices));
this.context = context;
this.devices = devices;
OpenCLObjectManager.getInstance().registerObject(this);
}
public CLContext getContext() {
@ -208,10 +208,6 @@ public class LwjglContext extends Context {
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;

View File

@ -41,31 +41,24 @@ import org.lwjgl.opencl.CLEvent;
*
* @author shaman
*/
public class LwjglEvent implements Event {
public class LwjglEvent extends Event {
private static final Logger LOG = Logger.getLogger(LwjglEvent.class.getName());
private CLEvent event;
private ReleaserImpl releaser;
public LwjglEvent(CLEvent event) {
super(new ReleaserImpl(event));
this.event = event;
if (event == null) {
LOG.warning("event is null!");
} else {
OpenCLObjectManager.getInstance().registerObject(this);
this.releaser = new ReleaserImpl(event);
}
}
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() {
@ -93,11 +86,6 @@ public class LwjglEvent implements Event {
}
}
@Override
public ObjectReleaser getReleaser() {
return new ReleaserImpl(event);
}
private static class ReleaserImpl implements ObjectReleaser {
private CLEvent event;

View File

@ -43,14 +43,14 @@ import org.lwjgl.opencl.api.CLImageFormat;
*
* @author shaman
*/
public class LwjglImage implements Image {
public class LwjglImage extends Image {
private static final Logger LOG = Logger.getLogger(LwjglImage.class.getName());
private final CLMem image;
public LwjglImage(CLMem image) {
super(new ReleaserImpl(image));
this.image = image;
OpenCLObjectManager.getInstance().registerObject(this);
}
public CLMem getImage() {
@ -543,10 +543,6 @@ public class LwjglImage implements Image {
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) {

View File

@ -52,8 +52,8 @@ public class LwjglKernel extends Kernel {
private final CLKernel kernel;
public LwjglKernel(CLKernel kernel) {
super(new ReleaserImpl(kernel));
this.kernel = kernel;
OpenCLObjectManager.getInstance().registerObject(this);
}
public CLKernel getKernel() {

View File

@ -44,16 +44,16 @@ import org.lwjgl.opencl.*;
*
* @author shaman
*/
public class LwjglProgram implements Program {
public class LwjglProgram extends Program {
private static final Logger LOG = Logger.getLogger(LwjglProgram.class.getName());
private final CLProgram program;
private final LwjglContext context;
public LwjglProgram(CLProgram program, LwjglContext context) {
super(new ReleaserImpl(program));
this.program = program;
this.context = context;
OpenCLObjectManager.getInstance().registerObject(this);
}
public CLProgram getProgram() {
@ -75,11 +75,6 @@ public class LwjglProgram implements Program {
LOG.log(Level.INFO, "Program compiled:\n{0}", Log());
}
}
@Override
public void build() throws KernelCompilationException {
build("");
}
private String Log() {
StringBuilder str = new StringBuilder();
@ -109,10 +104,6 @@ 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) {