diff options
author | Michael Bien <[email protected]> | 2010-01-29 14:36:19 +0100 |
---|---|---|
committer | Michael Bien <[email protected]> | 2010-01-29 14:36:19 +0100 |
commit | 2015fa5cd47b9be234f30e4b98d06b83486e4fb2 (patch) | |
tree | a03a73f6875e06ebdf8a910d939556ee139a9cb2 /src/com/mbien | |
parent | b0102cab5062eb8cb06329bff457d4dd5b9d0099 (diff) |
splitted CLImageFormat into CLImageFormat and (generated) CLImageFormatImpl.
refactored CLProgram kernel creation code.
updated tests.
Diffstat (limited to 'src/com/mbien')
-rw-r--r-- | src/com/mbien/opencl/CLGLBuffer.java | 21 | ||||
-rw-r--r-- | src/com/mbien/opencl/CLImage2d.java | 2 | ||||
-rw-r--r-- | src/com/mbien/opencl/CLImage3d.java | 2 | ||||
-rw-r--r-- | src/com/mbien/opencl/CLImageFormat.java | 277 | ||||
-rw-r--r-- | src/com/mbien/opencl/CLKernel.java | 19 | ||||
-rw-r--r-- | src/com/mbien/opencl/CLMemory.java | 53 | ||||
-rw-r--r-- | src/com/mbien/opencl/CLProgram.java | 158 |
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); } /** |