diff --git a/jme3-core/src/main/java/com/jme3/opencl/AbstractOpenCLObject.java b/jme3-core/src/main/java/com/jme3/opencl/AbstractOpenCLObject.java new file mode 100644 index 000000000..fce0f481d --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/opencl/AbstractOpenCLObject.java @@ -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; + } +} diff --git a/jme3-core/src/main/java/com/jme3/opencl/Buffer.java b/jme3-core/src/main/java/com/jme3/opencl/Buffer.java index 5bb474e36..66ce0c8f7 100644 --- a/jme3-core/src/main/java/com/jme3/opencl/Buffer.java +++ b/jme3-core/src/main/java/com/jme3/opencl/Buffer.java @@ -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) diff --git a/jme3-core/src/main/java/com/jme3/opencl/CommandQueue.java b/jme3-core/src/main/java/com/jme3/opencl/CommandQueue.java index 3fb5bcf6f..6d54237f9 100644 --- a/jme3-core/src/main/java/com/jme3/opencl/CommandQueue.java +++ b/jme3-core/src/main/java/com/jme3/opencl/CommandQueue.java @@ -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(); } diff --git a/jme3-core/src/main/java/com/jme3/opencl/Context.java b/jme3-core/src/main/java/com/jme3/opencl/Context.java index 5dbfa961c..10dde71fc 100644 --- a/jme3-core/src/main/java/com/jme3/opencl/Context.java +++ b/jme3-core/src/main/java/com/jme3/opencl/Context.java @@ -63,9 +63,13 @@ import java.util.logging.Logger; * * @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}. diff --git a/jme3-core/src/main/java/com/jme3/opencl/Event.java b/jme3-core/src/main/java/com/jme3/opencl/Event.java index 5399a97ef..44ea3da16 100644 --- a/jme3-core/src/main/java/com/jme3/opencl/Event.java +++ b/jme3-core/src/main/java/com/jme3/opencl/Event.java @@ -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(); } diff --git a/jme3-core/src/main/java/com/jme3/opencl/Image.java b/jme3-core/src/main/java/com/jme3/opencl/Image.java index 92545021a..e58c20f7e 100644 --- a/jme3-core/src/main/java/com/jme3/opencl/Image.java +++ b/jme3-core/src/main/java/com/jme3/opencl/Image.java @@ -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. * Important: 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 not 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 } diff --git a/jme3-core/src/main/java/com/jme3/opencl/Kernel.java b/jme3-core/src/main/java/com/jme3/opencl/Kernel.java index c7482a937..82fbf9018 100644 --- a/jme3-core/src/main/java/com/jme3/opencl/Kernel.java +++ b/jme3-core/src/main/java/com/jme3/opencl/Kernel.java @@ -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); } diff --git a/jme3-core/src/main/java/com/jme3/opencl/OpenCLObject.java b/jme3-core/src/main/java/com/jme3/opencl/OpenCLObject.java index 6ee0bc121..f9d631346 100644 --- a/jme3-core/src/main/java/com/jme3/opencl/OpenCLObject.java +++ b/jme3-core/src/main/java/com/jme3/opencl/OpenCLObject.java @@ -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(); } diff --git a/jme3-core/src/main/java/com/jme3/opencl/OpenCLObjectManager.java b/jme3-core/src/main/java/com/jme3/opencl/OpenCLObjectManager.java index 7895781d3..1d29a829f 100644 --- a/jme3-core/src/main/java/com/jme3/opencl/OpenCLObjectManager.java +++ b/jme3-core/src/main/java/com/jme3/opencl/OpenCLObjectManager.java @@ -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); } } diff --git a/jme3-core/src/main/java/com/jme3/opencl/Program.java b/jme3-core/src/main/java/com/jme3/opencl/Program.java index 8774b7c45..3cfe7bf05 100644 --- a/jme3-core/src/main/java/com/jme3/opencl/Program.java +++ b/jme3-core/src/main/java/com/jme3/opencl/Program.java @@ -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(); } diff --git a/jme3-examples/src/main/java/jme3test/opencl/HelloOpenCL.java b/jme3-examples/src/main/java/jme3test/opencl/HelloOpenCL.java index 4100fd92b..e08802785 100644 --- a/jme3-examples/src/main/java/jme3test/opencl/HelloOpenCL.java +++ b/jme3-examples/src/main/java/jme3test/opencl/HelloOpenCL.java @@ -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; diff --git a/jme3-examples/src/main/java/jme3test/opencl/TestVertexBufferSharing.java b/jme3-examples/src/main/java/jme3test/opencl/TestVertexBufferSharing.java index 06e2684dc..0d2257817 100644 --- a/jme3-examples/src/main/java/jme3test/opencl/TestVertexBufferSharing.java +++ b/jme3-examples/src/main/java/jme3test/opencl/TestVertexBufferSharing.java @@ -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(); } } \ No newline at end of file diff --git a/jme3-examples/src/main/java/jme3test/opencl/TestWriteToTexture.java b/jme3-examples/src/main/java/jme3test/opencl/TestWriteToTexture.java index 5230fb69d..c1f3e612f 100644 --- a/jme3-examples/src/main/java/jme3test/opencl/TestWriteToTexture.java +++ b/jme3-examples/src/main/java/jme3test/opencl/TestWriteToTexture.java @@ -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 diff --git a/jme3-jogl/src/main/java/com/jme3/opencl/jocl/JoclBuffer.java b/jme3-jogl/src/main/java/com/jme3/opencl/jocl/JoclBuffer.java index 773b581b1..06d417827 100644 --- a/jme3-jogl/src/main/java/com/jme3/opencl/jocl/JoclBuffer.java +++ b/jme3-jogl/src/main/java/com/jme3/opencl/jocl/JoclBuffer.java @@ -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) { diff --git a/jme3-jogl/src/main/java/com/jme3/opencl/jocl/JoclCommandQueue.java b/jme3-jogl/src/main/java/com/jme3/opencl/jocl/JoclCommandQueue.java index 790bc152b..e7b8a3743 100644 --- a/jme3-jogl/src/main/java/com/jme3/opencl/jocl/JoclCommandQueue.java +++ b/jme3-jogl/src/main/java/com/jme3/opencl/jocl/JoclCommandQueue.java @@ -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"); } diff --git a/jme3-jogl/src/main/java/com/jme3/opencl/jocl/JoclContext.java b/jme3-jogl/src/main/java/com/jme3/opencl/jocl/JoclContext.java index 4e9b6e920..eca2db012 100644 --- a/jme3-jogl/src/main/java/com/jme3/opencl/jocl/JoclContext.java +++ b/jme3-jogl/src/main/java/com/jme3/opencl/jocl/JoclContext.java @@ -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 devices; public JoclContext(CLContext context, List 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 devices; diff --git a/jme3-jogl/src/main/java/com/jme3/opencl/jocl/JoclEvent.java b/jme3-jogl/src/main/java/com/jme3/opencl/jocl/JoclEvent.java index cb6fa9235..c79504dfa 100644 --- a/jme3-jogl/src/main/java/com/jme3/opencl/jocl/JoclEvent.java +++ b/jme3-jogl/src/main/java/com/jme3/opencl/jocl/JoclEvent.java @@ -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; diff --git a/jme3-jogl/src/main/java/com/jme3/opencl/jocl/JoclImage.java b/jme3-jogl/src/main/java/com/jme3/opencl/jocl/JoclImage.java index aa6ce5ae7..0041147f9 100644 --- a/jme3-jogl/src/main/java/com/jme3/opencl/jocl/JoclImage.java +++ b/jme3-jogl/src/main/java/com/jme3/opencl/jocl/JoclImage.java @@ -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) { diff --git a/jme3-jogl/src/main/java/com/jme3/opencl/jocl/JoclKernel.java b/jme3-jogl/src/main/java/com/jme3/opencl/jocl/JoclKernel.java index b7d99c5bc..43bac1a30 100644 --- a/jme3-jogl/src/main/java/com/jme3/opencl/jocl/JoclKernel.java +++ b/jme3-jogl/src/main/java/com/jme3/opencl/jocl/JoclKernel.java @@ -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) { diff --git a/jme3-jogl/src/main/java/com/jme3/opencl/jocl/JoclProgram.java b/jme3-jogl/src/main/java/com/jme3/opencl/jocl/JoclProgram.java index dcc32014a..1714446cf 100644 --- a/jme3-jogl/src/main/java/com/jme3/opencl/jocl/JoclProgram.java +++ b/jme3-jogl/src/main/java/com/jme3/opencl/jocl/JoclProgram.java @@ -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) { diff --git a/jme3-lwjgl/src/main/java/com/jme3/opencl/lwjgl/LwjglBuffer.java b/jme3-lwjgl/src/main/java/com/jme3/opencl/lwjgl/LwjglBuffer.java index 60277427a..9a90c6eb1 100644 --- a/jme3-lwjgl/src/main/java/com/jme3/opencl/lwjgl/LwjglBuffer.java +++ b/jme3-lwjgl/src/main/java/com/jme3/opencl/lwjgl/LwjglBuffer.java @@ -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) { diff --git a/jme3-lwjgl/src/main/java/com/jme3/opencl/lwjgl/LwjglCommandQueue.java b/jme3-lwjgl/src/main/java/com/jme3/opencl/lwjgl/LwjglCommandQueue.java index a0fd04ddc..c413d6a8e 100644 --- a/jme3-lwjgl/src/main/java/com/jme3/opencl/lwjgl/LwjglCommandQueue.java +++ b/jme3-lwjgl/src/main/java/com/jme3/opencl/lwjgl/LwjglCommandQueue.java @@ -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) { diff --git a/jme3-lwjgl/src/main/java/com/jme3/opencl/lwjgl/LwjglContext.java b/jme3-lwjgl/src/main/java/com/jme3/opencl/lwjgl/LwjglContext.java index ad3450f8f..af5463f33 100644 --- a/jme3-lwjgl/src/main/java/com/jme3/opencl/lwjgl/LwjglContext.java +++ b/jme3-lwjgl/src/main/java/com/jme3/opencl/lwjgl/LwjglContext.java @@ -57,9 +57,9 @@ public class LwjglContext extends Context { private final List devices; public LwjglContext(CLContext context, List 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 devices; diff --git a/jme3-lwjgl/src/main/java/com/jme3/opencl/lwjgl/LwjglEvent.java b/jme3-lwjgl/src/main/java/com/jme3/opencl/lwjgl/LwjglEvent.java index 5055ac7af..1078c8c17 100644 --- a/jme3-lwjgl/src/main/java/com/jme3/opencl/lwjgl/LwjglEvent.java +++ b/jme3-lwjgl/src/main/java/com/jme3/opencl/lwjgl/LwjglEvent.java @@ -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; diff --git a/jme3-lwjgl/src/main/java/com/jme3/opencl/lwjgl/LwjglImage.java b/jme3-lwjgl/src/main/java/com/jme3/opencl/lwjgl/LwjglImage.java index 1ed59641b..46b8b0ff7 100644 --- a/jme3-lwjgl/src/main/java/com/jme3/opencl/lwjgl/LwjglImage.java +++ b/jme3-lwjgl/src/main/java/com/jme3/opencl/lwjgl/LwjglImage.java @@ -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) { diff --git a/jme3-lwjgl/src/main/java/com/jme3/opencl/lwjgl/LwjglKernel.java b/jme3-lwjgl/src/main/java/com/jme3/opencl/lwjgl/LwjglKernel.java index 21f165df6..1897e2501 100644 --- a/jme3-lwjgl/src/main/java/com/jme3/opencl/lwjgl/LwjglKernel.java +++ b/jme3-lwjgl/src/main/java/com/jme3/opencl/lwjgl/LwjglKernel.java @@ -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() { diff --git a/jme3-lwjgl/src/main/java/com/jme3/opencl/lwjgl/LwjglProgram.java b/jme3-lwjgl/src/main/java/com/jme3/opencl/lwjgl/LwjglProgram.java index a926c3d14..641951235 100644 --- a/jme3-lwjgl/src/main/java/com/jme3/opencl/lwjgl/LwjglProgram.java +++ b/jme3-lwjgl/src/main/java/com/jme3/opencl/lwjgl/LwjglProgram.java @@ -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) {