summaryrefslogtreecommitdiffstats
path: root/src/com/mbien/opencl
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/mbien/opencl')
-rw-r--r--src/com/mbien/opencl/CLBuffer.java127
-rw-r--r--src/com/mbien/opencl/CLCommandQueue.java38
-rw-r--r--src/com/mbien/opencl/CLContext.java98
-rw-r--r--src/com/mbien/opencl/CLDevice.java150
-rw-r--r--src/com/mbien/opencl/CLKernel.java3
-rw-r--r--src/com/mbien/opencl/CLProgram.java257
6 files changed, 408 insertions, 265 deletions
diff --git a/src/com/mbien/opencl/CLBuffer.java b/src/com/mbien/opencl/CLBuffer.java
index 185389c3..7c195ba7 100644
--- a/src/com/mbien/opencl/CLBuffer.java
+++ b/src/com/mbien/opencl/CLBuffer.java
@@ -9,7 +9,65 @@ import static com.mbien.opencl.CLException.*;
*/
public class CLBuffer {
- public enum MEM {
+ public final ByteBuffer buffer;
+ public final long ID;
+
+ private final CLContext context;
+ private final CL cl;
+
+ CLBuffer(CLContext context, ByteBuffer directBuffer, int flags) {
+
+ if(!directBuffer.isDirect())
+ throw new IllegalArgumentException("buffer is not a direct buffer");
+
+ this.buffer = directBuffer;
+ this.context = context;
+ this.cl = context.cl;
+
+ int[] intArray = new int[1];
+
+ this.ID = cl.clCreateBuffer(context.ID, flags, directBuffer.capacity(), null, intArray, 0);
+
+ checkForError(intArray[0], "can not create cl buffer");
+
+ }
+
+ public void release() {
+ int ret = cl.clReleaseMemObject(ID);
+ context.onBufferReleased(this);
+ checkForError(ret, "can not release mem object");
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final CLBuffer other = (CLBuffer) obj;
+ if (this.buffer != other.buffer && (this.buffer == null || !this.buffer.equals(other.buffer))) {
+ return false;
+ }
+ if (this.context.ID != other.context.ID) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 3;
+ hash = 29 * hash + (this.buffer != null ? this.buffer.hashCode() : 0);
+ hash = 29 * hash + (int) (this.context.ID ^ (this.context.ID >>> 32));
+ return hash;
+ }
+
+ /**
+ * Memory settings for configuring CLBuffers.
+ */
+ public enum Mem {
/**
* This flag specifies that the memory object will be read and
@@ -56,11 +114,11 @@ public class CLBuffer {
*/
public final int CL_FLAG;
- private MEM(int CL_TYPE) {
- this.CL_FLAG = CL_TYPE;
+ private Mem(int CL_FLAG) {
+ this.CL_FLAG = CL_FLAG;
}
- public static MEM valueOf(int bufferFlag) {
+ public static Mem valueOf(int bufferFlag) {
switch(bufferFlag) {
case(CL.CL_MEM_READ_WRITE):
return READ_WRITE;
@@ -76,7 +134,7 @@ public class CLBuffer {
return null;
}
- static int flagsToInt(MEM[] flags) {
+ static int flagsToInt(Mem[] flags) {
int clFlags = 0;
if(flags != null) {
for (int i = 0; i < flags.length; i++) {
@@ -90,63 +148,4 @@ public class CLBuffer {
}
-
- public final ByteBuffer buffer;
- public final long ID;
-
- private final CLContext context;
- private final CL cl;
-
- CLBuffer(CLContext context, ByteBuffer directBuffer, int flags) {
-
- if(!directBuffer.isDirect())
- throw new IllegalArgumentException("buffer is not a direct buffer");
-
- this.buffer = directBuffer;
- this.context = context;
- this.cl = context.cl;
-
- int[] intArray = new int[1];
-
- this.ID = cl.clCreateBuffer(context.ID, flags, directBuffer.capacity(), null, intArray, 0);
-
- checkForError(intArray[0], "can not create cl buffer");
-
- }
-
- public void release() {
- int ret = cl.clReleaseMemObject(ID);
- context.onBufferReleased(this);
- checkForError(ret, "can not release mem object");
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj == null) {
- return false;
- }
- if (getClass() != obj.getClass()) {
- return false;
- }
- final CLBuffer other = (CLBuffer) obj;
- if (this.buffer != other.buffer && (this.buffer == null || !this.buffer.equals(other.buffer))) {
- return false;
- }
- if (this.context.ID != other.context.ID) {
- return false;
- }
- return true;
- }
-
- @Override
- public int hashCode() {
- int hash = 3;
- hash = 29 * hash + (this.buffer != null ? this.buffer.hashCode() : 0);
- hash = 29 * hash + (int) (this.context.ID ^ (this.context.ID >>> 32));
- return hash;
- }
-
-
-
-
}
diff --git a/src/com/mbien/opencl/CLCommandQueue.java b/src/com/mbien/opencl/CLCommandQueue.java
index 5abc5cd5..00e1d6b0 100644
--- a/src/com/mbien/opencl/CLCommandQueue.java
+++ b/src/com/mbien/opencl/CLCommandQueue.java
@@ -3,7 +3,12 @@ package com.mbien.opencl;
import static com.mbien.opencl.CLException.*;
/**
- *
+ * The command-queue can be used to queue a set of operations in order. Having multiple
+ * command-queues allows applications to queue multiple independent commands without
+ * requiring synchronization. Note that this should work as long as these objects are
+ * not being shared.<b/>
+ * Sharing of objects across multiple command-queues will require the application to
+ * perform appropriate synchronization.
* @author Michael Bien
*/
public class CLCommandQueue {
@@ -190,5 +195,36 @@ public class CLCommandQueue {
return hash;
}
+ /**
+ * Enumeration for the command-queue settings.
+ */
+ public enum Mode {
+ /**
+ * CL_DEVICE_TYPE_CPU
+ */
+ OUT_OF_ORDER_EXEC_MODE(CL.CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE),
+ /**
+ * CL_DEVICE_TYPE_GPU
+ */
+ PROFILING_MODE(CL.CL_QUEUE_PROFILING_ENABLE);
+
+ /**
+ * Value of wrapped OpenCL device type.
+ */
+ public final int CL_QUEUE_MODE;
+
+ private Mode(int CL_VALUE) {
+ this.CL_QUEUE_MODE = CL_VALUE;
+ }
+ public static Mode valueOf(int queueMode) {
+ switch(queueMode) {
+ case(CL.CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE):
+ return OUT_OF_ORDER_EXEC_MODE;
+ case(CL.CL_QUEUE_PROFILING_ENABLE):
+ return PROFILING_MODE;
+ }
+ return null;
+ }
+ }
}
diff --git a/src/com/mbien/opencl/CLContext.java b/src/com/mbien/opencl/CLContext.java
index a82092bb..81ac58f0 100644
--- a/src/com/mbien/opencl/CLContext.java
+++ b/src/com/mbien/opencl/CLContext.java
@@ -1,6 +1,6 @@
package com.mbien.opencl;
-import com.mbien.opencl.CLBuffer.MEM;
+import com.mbien.opencl.CLBuffer.Mem;
import com.sun.gluegen.runtime.BufferFactory;
import com.sun.gluegen.runtime.CPU;
import java.io.BufferedReader;
@@ -19,7 +19,9 @@ import java.util.Map;
import static com.mbien.opencl.CLException.*;
/**
- *
+ * CLContext is responsible for managing objects such as command-queues, memory,
+ * program and kernel objects and for executing kernels on one or more devices
+ * specified in the context.
* @author Michael Bien
*/
public final class CLContext {
@@ -42,30 +44,71 @@ public final class CLContext {
this.queuesMap = new HashMap<CLDevice, List<CLCommandQueue>>();
}
+ private final void initDevices() {
+
+ if (devices == null) {
+
+ int sizeofDeviceID = CPU.is32Bit() ? 4 : 8;
+ long[] longBuffer = new long[1];
+
+ int ret = cl.clGetContextInfo(ID, CL.CL_CONTEXT_DEVICES, 0, null, longBuffer, 0);
+ checkForError(ret, "can not enumerate devices");
+
+ ByteBuffer deviceIDs = ByteBuffer.allocate((int) longBuffer[0]).order(ByteOrder.nativeOrder());
+ ret = cl.clGetContextInfo(ID, CL.CL_CONTEXT_DEVICES, deviceIDs.capacity(), deviceIDs, null, 0);
+ checkForError(ret, "can not enumerate devices");
+
+ devices = new CLDevice[deviceIDs.capacity() / sizeofDeviceID];
+ for (int i = 0; i < devices.length; i++) {
+ devices[i] = new CLDevice(this, CPU.is32Bit() ? deviceIDs.getInt() : deviceIDs.getLong());
+ }
+ }
+ }
+
/**
- * Creates a default context on all available devices.
+ * Creates a default context on all available devices (CL_DEVICE_TYPE_ALL).
+ * The platform to be used is implementation dependent.
*/
public static final CLContext create() {
- return createContext(CL.CL_DEVICE_TYPE_ALL);
+ return createContext(null, CL.CL_DEVICE_TYPE_ALL);
}
/**
* Creates a default context on the specified device types.
+ * The platform to be used is implementation dependent.
*/
public static final CLContext create(CLDevice.Type... deviceTypes) {
+ return create(null, deviceTypes);
+ }
- int type = deviceTypes[0].CL_TYPE;
- for (int i = 1; i < deviceTypes.length; i++) {
- type |= deviceTypes[i].CL_TYPE;
+ // TODO check if driver bug, otherwise find the reason why this is not working (INVALID_VALUE with NV driver)
+ /**
+ * Creates a default context on the specified platform and with the specified
+ * device types.
+ */
+ private static final CLContext create(CLPlatform platform, CLDevice.Type... deviceTypes) {
+
+ int type = 0;
+ if(deviceTypes != null) {
+ for (int i = 0; i < deviceTypes.length; i++) {
+ type |= deviceTypes[i].CL_TYPE;
+ }
}
- return createContext(type);
+ IntBuffer properties = null;
+ if(platform != null) {
+ properties = IntBuffer.allocate(3);
+ properties.put(CL.CL_CONTEXT_PLATFORM).put((int)platform.ID).put(0); // TODO check if this has to be int or long
+ properties.rewind();
+ }
+
+ return createContext(properties, type);
}
- private static final CLContext createContext(long deviceType) {
+ private static final CLContext createContext(IntBuffer properties, long deviceType) {
IntBuffer status = IntBuffer.allocate(1);
- long context = CLPlatform.getLowLevelBinding().clCreateContextFromType(null, 0, deviceType, null, null, status, 0);
+ long context = CLPlatform.getLowLevelBinding().clCreateContextFromType(properties, deviceType, null, null, status);
checkForError(status.get(), "can not create CL context");
@@ -104,14 +147,14 @@ public final class CLContext {
/**
* Creates a CLBuffer with the specified flags. No flags creates a MEM.READ_WRITE buffer.
*/
- public CLBuffer createBuffer(ByteBuffer directBuffer, MEM... flags) {
- return createBuffer(directBuffer, MEM.flagsToInt(flags));
+ public CLBuffer createBuffer(ByteBuffer directBuffer, Mem... flags) {
+ return createBuffer(directBuffer, Mem.flagsToInt(flags));
}
/**
* Creates a CLBuffer with the specified flags. No flags creates a MEM.READ_WRITE buffer.
*/
- public CLBuffer createBuffer(int size, MEM... flags) {
- return createBuffer(size, MEM.flagsToInt(flags));
+ public CLBuffer createBuffer(int size, Mem... flags) {
+ return createBuffer(size, Mem.flagsToInt(flags));
}
public CLBuffer createBuffer(int size, int flags) {
@@ -187,6 +230,8 @@ public final class CLContext {
/**
* Gets the device with maximal FLOPS from this context.
+ * The device speed is estimated by calulating the product of
+ * MAX_COMPUTE_UNITS and MAX_CLOCK_FREQUENCY.
*/
public CLDevice getMaxFlopsDevice() {
@@ -215,29 +260,7 @@ public final class CLContext {
* Returns all devices associated with this CLContext.
*/
public CLDevice[] getCLDevices() {
-
- if(devices == null) {
-
- int sizeofDeviceID = CPU.is32Bit()?4:8;
-
- long[] longBuffer = new long[1];
-
- int ret;
- ret = cl.clGetContextInfo(ID, CL.CL_CONTEXT_DEVICES, 0, null, longBuffer, 0);
- checkForError(ret, "can not enumerate devices");
-
- ByteBuffer deviceIDs = ByteBuffer.allocate((int)longBuffer[0]).order(ByteOrder.nativeOrder());
-
- ret = cl.clGetContextInfo(ID, CL.CL_CONTEXT_DEVICES, deviceIDs.capacity(), deviceIDs, null, 0);
- checkForError(ret, "can not enumerate devices");
-
- devices = new CLDevice[deviceIDs.capacity()/sizeofDeviceID];
- for (int i = 0; i < devices.length; i++) {
- devices[i] = new CLDevice(this,
- CPU.is32Bit()?deviceIDs.getInt():deviceIDs.getLong());
- }
- }
-
+ initDevices();
return devices;
}
@@ -279,5 +302,4 @@ public final class CLContext {
return hash;
}
-
}
diff --git a/src/com/mbien/opencl/CLDevice.java b/src/com/mbien/opencl/CLDevice.java
index 87616516..0ad8f0e9 100644
--- a/src/com/mbien/opencl/CLDevice.java
+++ b/src/com/mbien/opencl/CLDevice.java
@@ -15,51 +15,6 @@ import static com.mbien.opencl.CLException.*;
*/
public final class CLDevice {
- /**
- * Enumeration for the type of a device.
- */
- public enum Type {
- /**
- * CL_DEVICE_TYPE_CPU
- */
- CPU(CL.CL_DEVICE_TYPE_CPU),
- /**
- * CL_DEVICE_TYPE_GPU
- */
- GPU(CL.CL_DEVICE_TYPE_GPU),
- /**
- * CL_DEVICE_TYPE_ACCELERATOR
- */
- ACCELERATOR(CL.CL_DEVICE_TYPE_ACCELERATOR),
- /**
- * CL_DEVICE_TYPE_DEFAULT
- */
- DEFAULT(CL.CL_DEVICE_TYPE_DEFAULT);
-
- /**
- * Value of wrapped OpenCL device type.
- */
- public final int CL_TYPE;
-
- private Type(int CL_TYPE) {
- this.CL_TYPE = CL_TYPE;
- }
-
- public static Type valueOf(int clDeviceType) {
- switch(clDeviceType) {
- case(CL.CL_DEVICE_TYPE_DEFAULT):
- return DEFAULT;
- case(CL.CL_DEVICE_TYPE_CPU):
- return CPU;
- case(CL.CL_DEVICE_TYPE_GPU):
- return GPU;
- case(CL.CL_DEVICE_TYPE_ACCELERATOR):
- return ACCELERATOR;
- }
- return null;
- }
- }
-
private final CL cl;
private CLContext context;
@@ -82,6 +37,20 @@ public final class CLDevice {
public CLCommandQueue createCommandQueue() {
return createCommandQueue(0);
}
+
+ public CLCommandQueue createCommandQueue(CLCommandQueue.Mode property) {
+ return createCommandQueue(property.CL_QUEUE_MODE);
+ }
+
+ public CLCommandQueue createCommandQueue(CLCommandQueue.Mode... properties) {
+ int flags = 0;
+ if(properties != null) {
+ for (int i = 0; i < properties.length; i++) {
+ flags |= properties[i].CL_QUEUE_MODE;
+ }
+ }
+ return createCommandQueue(flags);
+ }
public CLCommandQueue createCommandQueue(long properties) {
if(context == null)
@@ -123,41 +92,77 @@ public final class CLDevice {
}
/**
- * Returns the maximal number of compute units.
+ * Returns the number of parallel compute cores on the OpenCL device.
+ * The minimum value is 1.
*/
public int getMaxComputeUnits() {
return (int) getInfoLong(CL.CL_DEVICE_MAX_COMPUTE_UNITS);
}
/**
- * Returns the maximal work group size.
+ * Returns the maximum number of work-items in a work-group executing
+ * a kernel using the data parallel execution model.
+ * The minimum value is 1.
*/
public int getMaxWorkGroupSize() {
return (int) getInfoLong(CL.CL_DEVICE_MAX_WORK_GROUP_SIZE);
}
/**
- * Returns the max clock frequency in Hz.
+ * Returns the maximum configured clock frequency of the device in MHz.
*/
public int getMaxClockFrequency() {
return (int) (getInfoLong(CL.CL_DEVICE_MAX_CLOCK_FREQUENCY));
}
/**
- * Returns the global memory size in Bytes.
+ * Returns the maximum dimensions that specify the global and local work-item
+ * IDs used by the data parallel execution model.
+ * The minimum value is 3.
+ */
+ public int getMaxWorkItemDimensions() {
+ return (int) getInfoLong(CL.CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS);
+ }
+
+ /**
+ * Returns the global memory size in bytes.
*/
public long getGlobalMemSize() {
return getInfoLong(CL.CL_DEVICE_GLOBAL_MEM_SIZE);
}
/**
- * Returns the local memory size in Bytes.
+ * Returns the local memory size in bytes.
*/
public long getLocalMemSize() {
return getInfoLong(CL.CL_DEVICE_LOCAL_MEM_SIZE);
}
/**
+ * Returns the max size in bytes of a constant buffer allocation.
+ * The minimum value is 64 KB.
+ */
+ public long getMaxConstantBufferSize() {
+ return getInfoLong(CL.CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE);
+ }
+
+ /**
+ * Returns true if this device is available.
+ */
+ public boolean isAvailable() {
+ return getInfoLong(CL.CL_DEVICE_AVAILABLE) == CL.CL_TRUE;
+ }
+
+ /**
+ * Returns false if the implementation does not have a compiler available to
+ * compile the program source. Is true if the compiler is available.
+ * This can be false for the OpenCL ES profile only.
+ */
+ public boolean isCompilerAvailable() {
+ return getInfoLong(CL.CL_DEVICE_COMPILER_AVAILABLE) == CL.CL_TRUE;
+ }
+
+ /**
* Returns all device extension names as unmodifiable Set.
*/
public Set<String> getExtensions() {
@@ -233,4 +238,49 @@ public final class CLDevice {
return hash;
}
+ /**
+ * Enumeration for the type of a device.
+ */
+ public enum Type {
+ /**
+ * CL_DEVICE_TYPE_CPU
+ */
+ CPU(CL.CL_DEVICE_TYPE_CPU),
+ /**
+ * CL_DEVICE_TYPE_GPU
+ */
+ GPU(CL.CL_DEVICE_TYPE_GPU),
+ /**
+ * CL_DEVICE_TYPE_ACCELERATOR
+ */
+ ACCELERATOR(CL.CL_DEVICE_TYPE_ACCELERATOR),
+ /**
+ * CL_DEVICE_TYPE_DEFAULT
+ */
+ DEFAULT(CL.CL_DEVICE_TYPE_DEFAULT);
+
+ /**
+ * Value of wrapped OpenCL device type.
+ */
+ public final int CL_TYPE;
+
+ private Type(int CL_TYPE) {
+ this.CL_TYPE = CL_TYPE;
+ }
+
+ public static Type valueOf(int clDeviceType) {
+ switch(clDeviceType) {
+ case(CL.CL_DEVICE_TYPE_DEFAULT):
+ return DEFAULT;
+ case(CL.CL_DEVICE_TYPE_CPU):
+ return CPU;
+ case(CL.CL_DEVICE_TYPE_GPU):
+ return GPU;
+ case(CL.CL_DEVICE_TYPE_ACCELERATOR):
+ return ACCELERATOR;
+ }
+ return null;
+ }
+ }
+
}
diff --git a/src/com/mbien/opencl/CLKernel.java b/src/com/mbien/opencl/CLKernel.java
index 838f5969..3388251b 100644
--- a/src/com/mbien/opencl/CLKernel.java
+++ b/src/com/mbien/opencl/CLKernel.java
@@ -76,6 +76,9 @@ public class CLKernel {
return BufferFactory.newDirectByteBuffer(8).putLong(value).rewind();
}
+ /**
+ * Releases all resources of this kernel from its context.
+ */
public void release() {
int ret = cl.clReleaseKernel(ID);
program.onKernelReleased(this);
diff --git a/src/com/mbien/opencl/CLProgram.java b/src/com/mbien/opencl/CLProgram.java
index 70656373..ff2919e8 100644
--- a/src/com/mbien/opencl/CLProgram.java
+++ b/src/com/mbien/opencl/CLProgram.java
@@ -21,39 +21,6 @@ public class CLProgram {
private final Map<String, CLKernel> kernels;
- public enum Status {
-
- BUILD_SUCCESS(CL.CL_BUILD_SUCCESS),
- BUILD_NONE(CL.CL_BUILD_NONE),
- BUILD_IN_PROGRESS(CL.CL_BUILD_IN_PROGRESS),
- BUILD_ERROR(CL.CL_BUILD_ERROR);
-
- /**
- * Value of wrapped OpenCL device type.
- */
- public final int CL_BUILD_STATUS;
-
- private Status(int CL_BUILD_STATUS) {
- this.CL_BUILD_STATUS = CL_BUILD_STATUS;
- }
-
- public static Status valueOf(int clBuildStatus) {
- switch(clBuildStatus) {
- case(CL.CL_BUILD_SUCCESS):
- return BUILD_SUCCESS;
- case(CL.CL_BUILD_NONE):
- return BUILD_NONE;
- case(CL.CL_BUILD_IN_PROGRESS):
- return BUILD_IN_PROGRESS;
- case(CL.CL_BUILD_ERROR):
- return BUILD_ERROR;
-// is this a standard state?
-// case (CL.CL_BUILD_PROGRAM_FAILURE):
-// return BUILD_PROGRAM_FAILURE;
- }
- return null;
- }
- }
CLProgram(CLContext context, String src, long contextID) {
@@ -68,6 +35,76 @@ public class CLProgram {
checkForError(intArray[0], "can not create program with source");
}
+ private final void initKernels() {
+
+ if(kernels.isEmpty()) {
+ int[] intArray = new int[1];
+ int ret = cl.clCreateKernelsInProgram(ID, 0, null, 0, intArray, 0);
+ checkForError(ret, "can not create kernels for program");
+
+ long[] kernelIDs = new long[intArray[0]];
+ ret = cl.clCreateKernelsInProgram(ID, kernelIDs.length, kernelIDs, 0, null, 0);
+ checkForError(ret, "can not create kernels for program");
+
+ for (int i = 0; i < intArray[0]; i++) {
+ CLKernel kernel = new CLKernel(this, kernelIDs[i]);
+ kernels.put(kernel.name, kernel);
+ }
+ }
+ }
+
+ // TODO serialization, program build options
+
+ private final String getBuildInfoString(long device, int flag) {
+
+ long[] longArray = new long[1];
+
+ int ret = cl.clGetProgramBuildInfo(ID, device, flag, 0, null, longArray, 0);
+ checkForError(ret, "on clGetProgramBuildInfo");
+
+ ByteBuffer bb = ByteBuffer.allocate((int)longArray[0]).order(ByteOrder.nativeOrder());
+
+ ret = cl.clGetProgramBuildInfo(ID, device, flag, bb.capacity(), bb, null, 0);
+ checkForError(ret, "on clGetProgramBuildInfo");
+
+ return new String(bb.array(), 0, (int)longArray[0]);
+ }
+
+ private final String getProgramInfoString(int flag) {
+
+ long[] longArray = new long[1];
+
+ int ret = cl.clGetProgramInfo(ID, flag, 0, null, longArray, 0);
+ checkForError(ret, "on clGetProgramInfo");
+
+ ByteBuffer bb = ByteBuffer.allocate((int)longArray[0]).order(ByteOrder.nativeOrder());
+
+ ret = cl.clGetProgramInfo(ID, flag, bb.capacity(), bb, null, 0);
+ checkForError(ret, "on clGetProgramInfo");
+
+ return new String(bb.array(), 0, (int)longArray[0]);
+ }
+
+// private int getProgramInfoInt(int flag) {
+//
+// ByteBuffer bb = ByteBuffer.allocate(4).order(ByteOrder.nativeOrder());
+//
+// int ret = cl.clGetProgramInfo(programID, flag, bb.capacity(), bb, null, 0);
+// checkForError(ret, "");
+//
+// return bb.getInt();
+// }
+
+ private int getBuildInfoInt(long device, int flag) {
+
+ ByteBuffer bb = ByteBuffer.allocate(4).order(ByteOrder.nativeOrder());
+
+ int ret = cl.clGetProgramBuildInfo(ID, device, flag, bb.capacity(), bb, null, 0);
+ checkForError(ret, "error on clGetProgramBuildInfo");
+
+ return bb.getInt();
+ }
+
/**
* Builds this program for all devices associated with the context and implementation specific build options.
@@ -79,6 +116,15 @@ public class CLProgram {
}
/**
+ * Builds this program for all devices associated with the context using the specified build options.
+ * @return this
+ */
+ public CLProgram build(String options) {
+ build(null, options);
+ return this;
+ }
+
+ /**
* Builds this program for the given devices and with the specified build options.
* @return this
* @param devices A list of devices this program should be build on or null for all devices of its context.
@@ -100,30 +146,6 @@ public class CLProgram {
return this;
}
- /**
- * 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(kernels.isEmpty()) {
-
- int[] intArray = new int[1];
- int ret = cl.clCreateKernelsInProgram(ID, 0, null, 0, intArray, 0);
- checkForError(ret, "can not create kernels for program");
-
- long[] kernelIDs = new long[intArray[0]];
- ret = cl.clCreateKernelsInProgram(ID, kernelIDs.length, kernelIDs, 0, null, 0);
- checkForError(ret, "can not create kernels for program");
-
- for (int i = 0; i < intArray[0]; i++) {
- CLKernel kernel = new CLKernel(this, kernelIDs[i]);
- kernels.put(kernel.name, kernel);
- }
- }
-
- return Collections.unmodifiableMap(kernels);
- }
-
void onKernelReleased(CLKernel kernel) {
this.kernels.remove(kernel.name);
}
@@ -147,6 +169,24 @@ public class CLProgram {
}
/**
+ * Returns the kernel with the specified name or null if not found.
+ */
+ public CLKernel getCLKernel(String kernelName) {
+ initKernels();
+ return kernels.get(kernelName);
+ }
+
+
+ /**
+ * 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() {
+ initKernels();
+ return Collections.unmodifiableMap(kernels);
+ }
+
+ /**
* Returns all devices associated with this program.
*/
public CLDevice[] getCLDevices() {
@@ -169,22 +209,34 @@ public class CLProgram {
}
+ /**
+ * Returns the build log for this program. The contents of the log are
+ * implementation dependent log can be an empty String.
+ */
public String getBuildLog(CLDevice device) {
return getBuildInfoString(device.ID, CL.CL_PROGRAM_BUILD_LOG);
}
+ /**
+ * Returns the build status enum for this program on the specified device.
+ */
public Status getBuildStatus(CLDevice device) {
int clStatus = getBuildInfoInt(device.ID, CL.CL_PROGRAM_BUILD_STATUS);
return Status.valueOf(clStatus);
}
/**
- * Returns the source code of this program. Note: sources are not cached, each call of this method calls into OpenCL.
+ * Returns the source code of this program. Note: sources are not cached,
+ * each call of this method calls into OpenCL.
*/
public String getSource() {
return getProgramInfoString(CL.CL_PROGRAM_SOURCE);
}
+ /**
+ * Returns the binaries for this program in a map containing the device as key
+ * and the byte array as value.
+ */
public Map<CLDevice, byte[]> getBinaries() {
CLDevice[] devices = getCLDevices();
@@ -198,7 +250,7 @@ public class CLProgram {
binarySize += (int)sizes.getLong();
ByteBuffer binaries = ByteBuffer.allocate(binarySize).order(ByteOrder.nativeOrder());
- ret = cl.clGetProgramInfo(ID, CL.CL_PROGRAM_BINARIES, binaries.capacity(), binaries, null, 0); // crash, driver bug?
+ ret = cl.clGetProgramInfo(ID, CL.CL_PROGRAM_BINARIES, binaries.capacity(), binaries, null, 0); // TODO crash, driver bug?
checkForError(ret, "on clGetProgramInfo");
Map<CLDevice, byte[]> map = new HashMap<CLDevice, byte[]>();
@@ -212,59 +264,6 @@ public class CLProgram {
return map;
}
-
- // TODO serialization, program build options
-
- private final String getBuildInfoString(long device, int flag) {
-
- long[] longArray = new long[1];
-
- int ret = cl.clGetProgramBuildInfo(ID, device, flag, 0, null, longArray, 0);
- checkForError(ret, "on clGetProgramBuildInfo");
-
- ByteBuffer bb = ByteBuffer.allocate((int)longArray[0]).order(ByteOrder.nativeOrder());
-
- ret = cl.clGetProgramBuildInfo(ID, device, flag, bb.capacity(), bb, null, 0);
- checkForError(ret, "on clGetProgramBuildInfo");
-
- return new String(bb.array(), 0, (int)longArray[0]);
- }
-
- private final String getProgramInfoString(int flag) {
-
- long[] longArray = new long[1];
-
- int ret = cl.clGetProgramInfo(ID, flag, 0, null, longArray, 0);
- checkForError(ret, "on clGetProgramInfo");
-
- ByteBuffer bb = ByteBuffer.allocate((int)longArray[0]).order(ByteOrder.nativeOrder());
-
- ret = cl.clGetProgramInfo(ID, flag, bb.capacity(), bb, null, 0);
- checkForError(ret, "on clGetProgramInfo");
-
- return new String(bb.array(), 0, (int)longArray[0]);
- }
-
-// private int getProgramInfoInt(int flag) {
-//
-// ByteBuffer bb = ByteBuffer.allocate(4).order(ByteOrder.nativeOrder());
-//
-// int ret = cl.clGetProgramInfo(programID, flag, bb.capacity(), bb, null, 0);
-// checkForError(ret, "");
-//
-// return bb.getInt();
-// }
-
- private int getBuildInfoInt(long device, int flag) {
-
- ByteBuffer bb = ByteBuffer.allocate(4).order(ByteOrder.nativeOrder());
-
- int ret = cl.clGetProgramBuildInfo(ID, device, flag, bb.capacity(), bb, null, 0);
- checkForError(ret, "error on clGetProgramBuildInfo");
-
- return bb.getInt();
- }
-
@Override
public boolean equals(Object obj) {
if (obj == null) {
@@ -290,5 +289,39 @@ public class CLProgram {
hash = 37 * hash + (int) (this.ID ^ (this.ID >>> 32));
return hash;
}
+
+ public enum Status {
+
+ BUILD_SUCCESS(CL.CL_BUILD_SUCCESS),
+ BUILD_NONE(CL.CL_BUILD_NONE),
+ BUILD_IN_PROGRESS(CL.CL_BUILD_IN_PROGRESS),
+ BUILD_ERROR(CL.CL_BUILD_ERROR);
+
+ /**
+ * Value of wrapped OpenCL device type.
+ */
+ public final int CL_BUILD_STATUS;
+
+ private Status(int CL_BUILD_STATUS) {
+ this.CL_BUILD_STATUS = CL_BUILD_STATUS;
+ }
+
+ public static Status valueOf(int clBuildStatus) {
+ switch(clBuildStatus) {
+ case(CL.CL_BUILD_SUCCESS):
+ return BUILD_SUCCESS;
+ case(CL.CL_BUILD_NONE):
+ return BUILD_NONE;
+ case(CL.CL_BUILD_IN_PROGRESS):
+ return BUILD_IN_PROGRESS;
+ case(CL.CL_BUILD_ERROR):
+ return BUILD_ERROR;
+// is this a standard state?
+// case (CL.CL_BUILD_PROGRAM_FAILURE):
+// return BUILD_PROGRAM_FAILURE;
+ }
+ return null;
+ }
+ }
}