summaryrefslogtreecommitdiffstats
path: root/src/com/mbien/opencl
diff options
context:
space:
mode:
authorMichael Bien <[email protected]>2010-01-29 14:36:19 +0100
committerMichael Bien <[email protected]>2010-01-29 14:36:19 +0100
commit2015fa5cd47b9be234f30e4b98d06b83486e4fb2 (patch)
treea03a73f6875e06ebdf8a910d939556ee139a9cb2 /src/com/mbien/opencl
parentb0102cab5062eb8cb06329bff457d4dd5b9d0099 (diff)
splitted CLImageFormat into CLImageFormat and (generated) CLImageFormatImpl.
refactored CLProgram kernel creation code. updated tests.
Diffstat (limited to 'src/com/mbien/opencl')
-rw-r--r--src/com/mbien/opencl/CLGLBuffer.java21
-rw-r--r--src/com/mbien/opencl/CLImage2d.java2
-rw-r--r--src/com/mbien/opencl/CLImage3d.java2
-rw-r--r--src/com/mbien/opencl/CLImageFormat.java277
-rw-r--r--src/com/mbien/opencl/CLKernel.java19
-rw-r--r--src/com/mbien/opencl/CLMemory.java53
-rw-r--r--src/com/mbien/opencl/CLProgram.java158
7 files changed, 426 insertions, 106 deletions
diff --git a/src/com/mbien/opencl/CLGLBuffer.java b/src/com/mbien/opencl/CLGLBuffer.java
index 566f45ec..40298ad7 100644
--- a/src/com/mbien/opencl/CLGLBuffer.java
+++ b/src/com/mbien/opencl/CLGLBuffer.java
@@ -11,12 +11,18 @@ import static com.mbien.opencl.CLGLI.*;
*/
public final class CLGLBuffer<B extends Buffer> extends CLBuffer<B> {
- private CLGLBuffer(CLContext context, B directBuffer, long id) {
+ /**
+ * The OpenGL object handle.
+ */
+ public final int GLID;
+
+ private CLGLBuffer(CLContext context, B directBuffer, long id, int glObject) {
super(context, directBuffer, id);
+ this.GLID = glObject;
}
- static <B extends Buffer> CLGLBuffer<B> create(CLContext context, B directBuffer, int flags, int glBuffer) {
+ static <B extends Buffer> CLGLBuffer<B> create(CLContext context, B directBuffer, int flags, int glObject) {
if(directBuffer != null && !directBuffer.isDirect())
throw new IllegalArgumentException("buffer is not a direct buffer");
@@ -29,14 +35,14 @@ public final class CLGLBuffer<B extends Buffer> extends CLBuffer<B> {
int[] result = new int[1];
CLGLI clgli = (CLGLI)cl;
- long id = clgli.clCreateFromGLBuffer(context.ID, flags, glBuffer, result, 0);
+ long id = clgli.clCreateFromGLBuffer(context.ID, flags, glObject, result, 0);
- return new CLGLBuffer<B>(context, directBuffer, id);
+ return new CLGLBuffer<B>(context, directBuffer, id, glObject);
}
@Override
public <T extends Buffer> CLGLBuffer<T> cloneWith(T directBuffer) {
- return new CLGLBuffer<T>(context, directBuffer, ID);
+ return new CLGLBuffer<T>(context, directBuffer, ID, GLID);
}
/**
@@ -59,6 +65,11 @@ public final class CLGLBuffer<B extends Buffer> extends CLBuffer<B> {
return array[0];
}
+ @Override
+ public String toString() {
+ return "CLMemory [id: " + ID+" glID: "+GLID+"]";
+ }
+
public enum GLObjectType {
GL_OBJECT_BUFFER(CL_GL_OBJECT_BUFFER),
diff --git a/src/com/mbien/opencl/CLImage2d.java b/src/com/mbien/opencl/CLImage2d.java
index fd1afcbf..882cedc4 100644
--- a/src/com/mbien/opencl/CLImage2d.java
+++ b/src/com/mbien/opencl/CLImage2d.java
@@ -22,7 +22,7 @@ public final class CLImage2d<B extends Buffer> extends CLImage<B> {
CL cl = context.cl;
IntBuffer err = BufferFactory.newDirectByteBuffer(4).asIntBuffer();
- long id = cl.clCreateImage2D(context.ID, flags, format, width, height, rowPitch, directBuffer, err);
+ long id = cl.clCreateImage2D(context.ID, flags, format.getFormatImpl(), width, height, rowPitch, directBuffer, err);
checkForError(err.get(), "can not create 2d image");
return new CLImage2d<B>(context, directBuffer, format, width, height, id);
diff --git a/src/com/mbien/opencl/CLImage3d.java b/src/com/mbien/opencl/CLImage3d.java
index fd5cde3e..2549ff21 100644
--- a/src/com/mbien/opencl/CLImage3d.java
+++ b/src/com/mbien/opencl/CLImage3d.java
@@ -26,7 +26,7 @@ public final class CLImage3d<B extends Buffer> extends CLImage<B> {
CL cl = context.cl;
IntBuffer err = BufferFactory.newDirectByteBuffer(4).asIntBuffer();
- long id = cl.clCreateImage3D(context.ID, flags, format, width, height, depth, rowPitch, slicePitch, directBuffer, err);
+ long id = cl.clCreateImage3D(context.ID, flags, format.getFormatImpl(), width, height, depth, rowPitch, slicePitch, directBuffer, err);
checkForError(err.get(), "can not create 2d image");
return new CLImage3d<B>(context, directBuffer, format, width, height, depth, id);
diff --git a/src/com/mbien/opencl/CLImageFormat.java b/src/com/mbien/opencl/CLImageFormat.java
new file mode 100644
index 00000000..b5551798
--- /dev/null
+++ b/src/com/mbien/opencl/CLImageFormat.java
@@ -0,0 +1,277 @@
+package com.mbien.opencl;
+
+import com.mbien.opencl.impl.CLImageFormatImpl;
+
+import static com.mbien.opencl.CL.*;
+
+/**
+ *
+ * @author Michael Bien
+ */
+public final class CLImageFormat {
+
+ private final CLImageFormatImpl format = CLImageFormatImpl.create();
+
+ public CLImageFormat(ChannelOrder order, ChannelType type) {
+ setImageChannelOrder(order);
+ setImageChannelDataType(type);
+ }
+
+ public CLImageFormat setImageChannelOrder(ChannelOrder order) {
+ format.setImageChannelOrder(order.ORDER);
+ return this;
+ }
+
+ public CLImageFormat setImageChannelDataType(ChannelType type) {
+ format.setImageChannelDataType(type.TYPE);
+ return this;
+ }
+
+ public ChannelOrder getImageChannelOrder() {
+ return ChannelOrder.valueOf(format.getImageChannelOrder());
+ }
+
+ public ChannelType getImageChannelDataType() {
+ return ChannelType.valueOf(format.getImageChannelDataType());
+ }
+
+ /**
+ * Returns the struct accessor for the cl_image_format struct.
+ */
+ public CLImageFormatImpl getFormatImpl() {
+ return format;
+ }
+
+ /**
+ * Specifies the number of channels and the channel layout i.e. the memory
+ * layout in which channels are stored in the image.
+ */
+ public enum ChannelOrder {
+
+ /**
+ *
+ */
+ R(CL_R),
+
+ /**
+ *
+ */
+ A(CL_A),
+
+ /**
+ *
+ */
+ RG(CL_RG),
+
+ /**
+ *
+ */
+ RA(CL_RA),
+
+ /**
+ * This format can only be used if channel data type is one of the following values:
+ * {@link ChannelType#UNORM_SHORT_565}, {@link ChannelType#UNORM_SHORT_555}
+ * or {@link ChannelType#UNORM_INT_101010}.
+ */
+ RGB(CL_RGB),
+
+ /**
+ *
+ */
+ RGBA(CL_RGBA),
+
+ /**
+ * This format can only be used if channel data type is one of the following values:
+ * {@link ChannelType#UNORM_INT8}, {@link ChannelType#SNORM_INT8}, {@link ChannelType#SIGNED_INT8}
+ * or {@link ChannelType#UNSIGNED_INT8}.
+ */
+ ARGB(CL_ARGB),
+
+ /**
+ * @see #ARGB
+ */
+ BGRA(CL_BGRA),
+
+ /**
+ * This format can only be used if channel data type is one of the following values:
+ * {@link ChannelType#UNORM_INT8}, {@link ChannelType#UNORM_INT16}, {@link ChannelType#SNORM_INT8},
+ * {@link ChannelType#SNORM_INT16}, {@link ChannelType#HALF_FLOAT}, or {@link ChannelType#FLOAT}.
+ */
+ INTENSITY(CL_INTENSITY),
+
+ /**
+ * This format can only be used if channel data type is one of the following values:
+ * {@link ChannelType#UNORM_INT8}, {@link ChannelType#UNORM_INT16}, {@link ChannelType#SNORM_INT8},
+ * {@link ChannelType#SNORM_INT16}, {@link ChannelType#HALF_FLOAT}, or {@link ChannelType#FLOAT}.
+ */
+ LUMINANCE(CL_LUMINANCE);
+
+
+ /**
+ * Value of wrapped OpenCL flag.
+ */
+ public final int ORDER;
+
+ private ChannelOrder(int order) {
+ this.ORDER = order;
+ }
+
+ public static ChannelOrder valueOf(int orderFlag) {
+ switch (orderFlag) {
+ case CL_R:
+ return R;
+ case CL_A:
+ return A;
+ case CL_INTENSITY:
+ return INTENSITY;
+ case CL_LUMINANCE:
+ return LUMINANCE;
+ case CL_RG:
+ return RG;
+ case CL_RA:
+ return RA;
+ case CL_RGB:
+ return RGB;
+ case CL_RGBA:
+ return RGBA;
+ case CL_ARGB:
+ return ARGB;
+ case CL_BGRA:
+ return BGRA;
+ }
+ return null;
+ }
+
+ }
+
+
+ /**
+ * Describes the size of the channel data type.
+ */
+ public enum ChannelType {
+
+ /**
+ * Each channel component is a normalized signed 8-bit integer value.
+ */
+ SNORM_INT8(CL_SNORM_INT8),
+
+ /**
+ * Each channel component is a normalized signed 16-bit integer value.
+ */
+ SNORM_INT16(CL_SNORM_INT16),
+
+ /**
+ * Each channel component is a normalized unsigned 8-bit integer value.
+ */
+ UNORM_INT8(CL_UNORM_INT8),
+
+ /**
+ * Each channel component is a normalized unsigned 16-bit integer value.
+ */
+ UNORM_INT16(CL_UNORM_INT16),
+
+ /**
+ * Represents a normalized 5-6-5 3-channel RGB image. The channel order must
+ * be {@link ChannelOrder#CL_RGB}.
+ */
+ UNORM_SHORT_565(CL_UNORM_SHORT_565),
+
+ /**
+ * Represents a normalized x-5-5-5 4-channel xRGB image. The channel order must
+ * be {@link ChannelOrder#RGB}.
+ */
+ UNORM_SHORT_555(CL_UNORM_SHORT_555),
+
+ /**
+ * Represents a normalized x-10-10-10 4-channel xRGB image. The channel order
+ * must be {@link ChannelOrder#RGB}.
+ */
+ UNORM_INT_101010(CL_UNORM_INT_101010),
+
+ /**
+ * Each channel component is an unnormalized signed 8-bit integer value.
+ */
+ SIGNED_INT8(CL_SIGNED_INT8),
+
+ /**
+ * Each channel component is an unnormalized signed 16-bit integer value.
+ */
+ SIGNED_INT16(CL_SIGNED_INT16),
+
+ /**
+ * Each channel component is an unnormalized signed 32-bit integer value.
+ */
+ SIGNED_INT32(CL_SIGNED_INT32),
+
+ /**
+ * Each channel component is an unnormalized unsigned 8-bit integer value.
+ */
+ UNSIGNED_INT8(CL_UNSIGNED_INT8),
+
+ /**
+ * Each channel component is an unnormalized unsigned 16-bit integer value.
+ */
+ UNSIGNED_INT16(CL_UNSIGNED_INT16),
+
+ /**
+ * Each channel component is an unnormalized unsigned 32-bit integer value.
+ */
+ UNSIGNED_INT32(CL_UNSIGNED_INT32),
+
+ /**
+ * Each channel component is a 16-bit half-float value.
+ */
+ HALF_FLOAT(CL_HALF_FLOAT),
+
+ /**
+ * Each channel component is a single precision floating-point value.
+ */
+ FLOAT(CL_FLOAT);
+
+ /**
+ * Value of wrapped OpenCL flag.
+ */
+ public final int TYPE;
+
+ private ChannelType(int channel) {
+ this.TYPE = channel;
+ }
+
+ public static ChannelType valueOf(int channelFlag) {
+ switch (channelFlag) {
+ case CL_SNORM_INT8:
+ return SNORM_INT8;
+ case CL_SNORM_INT16:
+ return SNORM_INT16;
+ case CL_UNORM_INT8:
+ return UNORM_INT8;
+ case CL_UNORM_INT16:
+ return UNORM_INT16;
+ case CL_UNORM_SHORT_565:
+ return UNORM_SHORT_565;
+ case CL_UNORM_SHORT_555:
+ return UNORM_SHORT_555;
+ case CL_UNORM_INT_101010:
+ return UNORM_INT_101010;
+ case CL_SIGNED_INT8:
+ return SIGNED_INT8;
+ case CL_SIGNED_INT16:
+ return SIGNED_INT16;
+ case CL_SIGNED_INT32:
+ return SIGNED_INT32;
+ case CL_UNSIGNED_INT8:
+ return UNSIGNED_INT8;
+ case CL_UNSIGNED_INT16:
+ return UNSIGNED_INT16;
+ case CL_UNSIGNED_INT32:
+ return UNSIGNED_INT32;
+ case CL_HALF_FLOAT:
+ return HALF_FLOAT;
+ case CL_FLOAT:
+ return FLOAT;
+ }
+ return null;
+ }
+
+ }
+}
diff --git a/src/com/mbien/opencl/CLKernel.java b/src/com/mbien/opencl/CLKernel.java
index 5e7330e7..cb03cf8e 100644
--- a/src/com/mbien/opencl/CLKernel.java
+++ b/src/com/mbien/opencl/CLKernel.java
@@ -19,7 +19,7 @@ import static com.mbien.opencl.CL.*;
* <code>kernel</code> function."
* @author Michael Bien
*/
-public class CLKernel implements CLResource {
+public class CLKernel implements CLResource/*, Cloneable*/ {
public final long ID;
public final String name;
@@ -129,7 +129,7 @@ public class CLKernel implements CLResource {
private final void setArgument(int argumentIndex, int size, Buffer value) {
if(argumentIndex >= numArgs || argumentIndex < 0) {
throw new IndexOutOfBoundsException("kernel "+ toString() +" has "+numArgs+
- " arguments, can not set argument number "+argumentIndex);
+ " arguments, can not set argument with index "+argumentIndex);
}
if(!program.isExecutable()) {
throw new IllegalStateException("can not set program" +
@@ -201,12 +201,13 @@ public class CLKernel implements CLResource {
hash = 43 * hash + (this.program != null ? this.program.hashCode() : 0);
return hash;
}
-
- CLKernel copy() {
- int[] err = new int[1];
- long newID = cl.clCreateKernel(program.ID, name, err, 0);
- checkForError(err[0], "can not copy kernel");
- return new CLKernel(program, newID);
- }
+
+ /**
+ * Returns a new instance of this kernel.
+ */
+// @Override
+// public CLKernel clone() {
+// return program.createCLKernel(name);
+// }
}
diff --git a/src/com/mbien/opencl/CLMemory.java b/src/com/mbien/opencl/CLMemory.java
index 836987e6..2b7e847a 100644
--- a/src/com/mbien/opencl/CLMemory.java
+++ b/src/com/mbien/opencl/CLMemory.java
@@ -10,6 +10,7 @@ import java.nio.IntBuffer;
import java.nio.ShortBuffer;
import static com.mbien.opencl.CLException.*;
+import static com.mbien.opencl.CL.*;
/**
*
@@ -38,7 +39,7 @@ public abstract class CLMemory <B extends Buffer> implements CLResource {
}
protected static final boolean isHostPointerFlag(int flags) {
- return (flags & CL.CL_MEM_COPY_HOST_PTR) != 0 || (flags & CL.CL_MEM_USE_HOST_PTR) != 0;
+ return (flags & CL_MEM_COPY_HOST_PTR) != 0 || (flags & CL_MEM_USE_HOST_PTR) != 0;
}
protected static final int sizeOfBufferElem(Buffer buffer) {
@@ -88,7 +89,7 @@ public abstract class CLMemory <B extends Buffer> implements CLResource {
public long getCLSize() {
PointerBuffer pb = PointerBuffer.allocateDirect(1);
- int ret = cl.clGetMemObjectInfo(ID, CL.CL_MEM_SIZE, PointerBuffer.elementSize(), pb.getBuffer(), null);
+ int ret = cl.clGetMemObjectInfo(ID, CL_MEM_SIZE, PointerBuffer.elementSize(), pb.getBuffer(), null);
checkForError(ret, "can not optain buffer info");
return pb.get();
}
@@ -125,52 +126,66 @@ public abstract class CLMemory <B extends Buffer> implements CLResource {
return hash;
}
+ @Override
+ public String toString() {
+ return "CLMemory [id: " + ID+"]";
+ }
+
/**
* Memory settings for configuring CLMemory.
*/
public enum Mem {
/**
+ * Enum representing CL_MEM_READ_WRITE.
* This flag specifies that the memory object will be read and
* written by a kernel.
*/
- READ_WRITE(CL.CL_MEM_READ_WRITE),
+ READ_WRITE(CL_MEM_READ_WRITE),
/**
+ * Enum representing CL_MEM_WRITE_ONLY.
* This flags specifies that the memory object will be written
* but not read by a kernel.
* Reading from a buffer or image object created with WRITE_ONLY
* inside a kernel is undefined.
*/
- WRITE_ONLY(CL.CL_MEM_WRITE_ONLY),
+ WRITE_ONLY(CL_MEM_WRITE_ONLY),
/**
+ * Enum representing CL_MEM_READ_ONLY.
* This flag specifies that the memory object is a read-only memory
* object when used inside a kernel. Writing to a buffer or image object
* created withREAD_ONLY inside a kernel is undefined.
*/
- READ_ONLY(CL.CL_MEM_READ_ONLY),
+ READ_ONLY(CL_MEM_READ_ONLY),
/**
- * Enum representing CL.CL_MEM_USE_HOST_PTR.
+ * Enum representing CL_MEM_USE_HOST_PTR.
* If specified, it indicates that the application wants the OpenCL
* implementation to use memory referenced by host_ptr as the storage
* bits for the memory object. OpenCL implementations are allowed
* to cache the buffer contents pointed to by host_ptr in device memory.
* This cached copy can be used when kernels are executed on a device.
*/
- USE_BUFFER(CL.CL_MEM_USE_HOST_PTR),
+ USE_BUFFER(CL_MEM_USE_HOST_PTR),
-// ALLOC_HOST_PTR(CL_MEM_ALLOC_HOST_PTR), // this is the default in java world anyway
+ /**
+ * Enum representing CL_MEM_ALLOC_HOST_PTR.
+ * This flag specifies that the application wants the OpenCL implementation
+ * to allocate memory from host accessible memory.
+ * {@link #ALLOC_HOST_PTR} and {@link #USE_BUFFER} are mutually exclusive.
+ */
+ ALLOC_HOST_PTR(CL_MEM_ALLOC_HOST_PTR),
/**
- * Enum representing CL.CL_MEM_COPY_HOST_PTR.
- * If CL_MEM_COPY_HOST_PTR specified, it indicates that the application
+ * Enum representing CL_MEM_COPY_HOST_PTR.
+ * If {@link #COPY_BUFFER} specified, it indicates that the application
* wants the OpenCL implementation to allocate memory for the memory object
* and copy the data from memory referenced by host_ptr.<br/>
- * COPY_HOST_PTR and USE_HOST_PTR are mutually exclusive.
+ * {@link #COPY_BUFFER} and {@link #USE_BUFFER} are mutually exclusive.
*/
- COPY_BUFFER(CL.CL_MEM_COPY_HOST_PTR);
+ COPY_BUFFER(CL_MEM_COPY_HOST_PTR);
/**
* Value of wrapped OpenCL flag.
@@ -183,15 +198,15 @@ public abstract class CLMemory <B extends Buffer> implements CLResource {
public static Mem valueOf(int bufferFlag) {
switch (bufferFlag) {
- case CL.CL_MEM_READ_WRITE:
+ case CL_MEM_READ_WRITE:
return Mem.READ_WRITE;
- case CL.CL_MEM_READ_ONLY:
+ case CL_MEM_READ_ONLY:
return Mem.READ_ONLY;
- case CL.CL_MEM_USE_HOST_PTR:
+ case CL_MEM_USE_HOST_PTR:
return Mem.USE_BUFFER;
-// case(CL_MEM_ALLOC_HOST_PTR):
-// return ALLOC_HOST_PTR;
- case CL.CL_MEM_COPY_HOST_PTR:
+ case(CL_MEM_ALLOC_HOST_PTR):
+ return ALLOC_HOST_PTR;
+ case CL_MEM_COPY_HOST_PTR:
return Mem.COPY_BUFFER;
}
return null;
@@ -205,7 +220,7 @@ public abstract class CLMemory <B extends Buffer> implements CLResource {
}
}
if (clFlags == 0) {
- clFlags = CL.CL_MEM_READ_WRITE;
+ clFlags = CL_MEM_READ_WRITE;
}
return clFlags;
}
diff --git a/src/com/mbien/opencl/CLProgram.java b/src/com/mbien/opencl/CLProgram.java
index 6f1ed551..dfe084c7 100644
--- a/src/com/mbien/opencl/CLProgram.java
+++ b/src/com/mbien/opencl/CLProgram.java
@@ -8,11 +8,12 @@ import java.nio.ByteOrder;
import java.nio.IntBuffer;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
import java.util.Map;
import static com.mbien.opencl.CLException.*;
import static com.mbien.opencl.CL.*;
-import java.util.Set;
/**
* Represents a OpenCL program executed on one or more {@link CLDevice}s.
@@ -25,7 +26,7 @@ public class CLProgram implements CLResource {
private final CL cl;
- private Map<String, CLKernel> kernels;
+ private final Set<CLKernel> kernels;
private Map<CLDevice, Status> buildStatusMap;
private boolean executable;
@@ -35,6 +36,7 @@ public class CLProgram implements CLResource {
this.cl = context.cl;
this.context = context;
+ this.kernels = new HashSet<CLKernel>();
IntBuffer ib = BufferFactory.newDirectByteBuffer(4).asIntBuffer();
// Create the program
@@ -47,6 +49,7 @@ public class CLProgram implements CLResource {
this.cl = context.cl;
this.context = context;
+ this.kernels = new HashSet<CLKernel>();
PointerBuffer devices = PointerBuffer.allocateDirect(binaries.size());
PointerBuffer lengths = PointerBuffer.allocateDirect(binaries.size());
@@ -80,38 +83,6 @@ public class CLProgram implements CLResource {
}
- private final void initKernels() {
-
- if(kernels == null) {
-
- IntBuffer numKernels = BufferFactory.newDirectByteBuffer(4).asIntBuffer();
- int ret = cl.clCreateKernelsInProgram(ID, 0, null, numKernels);
- checkForError(ret, "can not create kernels for program");
-
- if(numKernels.get(0) > 0) {
- HashMap<String, CLKernel> map = new HashMap<String, CLKernel>();
-
- PointerBuffer kernelIDs = PointerBuffer.allocateDirect(numKernels.get(0));
- ret = cl.clCreateKernelsInProgram(ID, kernelIDs.capacity(), kernelIDs, null);
- checkForError(ret, "can not create kernels for program");
-
- for (int i = 0; i < kernelIDs.capacity(); i++) {
- CLKernel kernel = new CLKernel(this, kernelIDs.get(i));
- map.put(kernel.name, kernel);
- }
- this.kernels = map;
- }else{
- initBuildStatus();
- if(!isExecutable()) {
- // It is illegal to create kernels from a not executable program.
- // For consistency between AMD and NVIDIA drivers throw an exception at this point.
- throw new CLException(CL_INVALID_PROGRAM_EXECUTABLE,
- "can not initialize kernels, program is not executable. status: "+buildStatusMap);
- }
- }
- }
- }
-
private final void initBuildStatus() {
if(buildStatusMap == null) {
@@ -235,7 +206,7 @@ public class CLProgram implements CLResource {
*/
public CLProgram build(String options, CLDevice... devices) {
- if(kernels != null) {
+ if(!kernels.isEmpty()) {
//No changes to the program executable are allowed while there are
//kernel objects associated with a program object.
releaseKernels();
@@ -266,8 +237,83 @@ public class CLProgram implements CLResource {
return this;
}
+ /**
+ * Creates a kernel with the specified kernel name.
+ */
+ public CLKernel createCLKernel(String kernelName) {
+
+ if(released) {
+ return null;
+ }
+
+ int[] err = new int[1];
+ long id = cl.clCreateKernel(ID, kernelName, err, 0);
+ checkForError(err[0], "unable to create Kernel with name: "+kernelName);
+
+ CLKernel kernel = new CLKernel(this, id);
+ kernels.add(kernel);
+ return kernel;
+ }
+
+ /**
+ * Creates n instances of a kernel with the specified kernel name.
+ */
+ /*
+ public CLKernel[] createCLKernels(String kernelName, int instanceCount) {
+
+ if(released) {
+ return new CLKernel[0];
+ }
+
+ CLKernel[] newKernels = new CLKernel[instanceCount];
+ for (int i = 0; i < newKernels.length; i++) {
+ newKernels[i] = createCLKernel(kernelName);
+ }
+ return newKernels;
+ }
+ */
+
+ /**
+ * Creates all kernels of this program and stores them a Map with the kernel name as key.
+ */
+ public Map<String, CLKernel> createCLKernels() {
+
+ if(released) {
+ return Collections.emptyMap();
+ }
+
+ HashMap<String, CLKernel> newKernels = new HashMap<String, CLKernel>();
+
+ IntBuffer numKernels = BufferFactory.newDirectByteBuffer(4).asIntBuffer();
+ int ret = cl.clCreateKernelsInProgram(ID, 0, null, numKernels);
+ checkForError(ret, "can not create kernels for program");
+
+ if(numKernels.get(0) > 0) {
+
+ PointerBuffer kernelIDs = PointerBuffer.allocateDirect(numKernels.get(0));
+ ret = cl.clCreateKernelsInProgram(ID, kernelIDs.capacity(), kernelIDs, null);
+ checkForError(ret, "can not create kernels for program");
+
+ for (int i = 0; i < kernelIDs.capacity(); i++) {
+ CLKernel kernel = new CLKernel(this, kernelIDs.get(i));
+ kernels.add(kernel);
+ newKernels.put(kernel.name, kernel);
+ }
+ }else{
+ initBuildStatus();
+ if(!isExecutable()) {
+ // It is illegal to create kernels from a not executable program.
+ // For consistency between AMD and NVIDIA drivers throw an exception at this point.
+ throw new CLException(CL_INVALID_PROGRAM_EXECUTABLE,
+ "can not initialize kernels, program is not executable. status: "+buildStatusMap);
+ }
+ }
+
+ return newKernels;
+ }
+
void onKernelReleased(CLKernel kernel) {
- this.kernels.remove(kernel.name);
+ this.kernels.remove(kernel);
}
/**
@@ -287,43 +333,13 @@ public class CLProgram implements CLResource {
}
private void releaseKernels() {
- if(kernels != null) {
- String[] names = kernels.keySet().toArray(new String[kernels.size()]);
- for (String name : names) {
- kernels.get(name).release();
+ if(!kernels.isEmpty()) {
+ // copy to array to prevent concurrent modification exception
+ CLKernel[] array = kernels.toArray(new CLKernel[kernels.size()]);
+ for (CLKernel kernel : array) {
+ kernel.release();
}
- kernels = null;
- }
- }
-
- /**
- * Returns the kernel with the specified name.
- * @throws IllegalArgumentException when no kernel with the specified name exists in this program.
- */
- public CLKernel getCLKernel(String kernelName) {
- if(released) {
- return null;
- }
- initKernels();
- final CLKernel kernel = kernels.get(kernelName);
- if(kernel == null) {
- throw new IllegalArgumentException(
- this+" does not contain a kernel with the name '"+kernelName+"'");
- }
- return kernel;
- }
-
-
- /**
- * Returns all kernels of this program in a unmodifiable view of a map
- * with the kernel function names as keys.
- */
- public Map<String, CLKernel> getCLKernels() {
- if(released) {
- return Collections.emptyMap();
}
- initKernels();
- return Collections.unmodifiableMap(kernels);
}
/**