summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMichael Bien <[email protected]>2009-10-19 02:56:04 +0200
committerMichael Bien <[email protected]>2009-10-19 02:56:04 +0200
commit9abfd00399e4ca5c351df9cdf25cd85c960b3d44 (patch)
tree0b44ac0da5c03fdd08a4039b25238c240bda1857 /src
parent01ae874925c4471d76ee6b18f15bf201c6f12f48 (diff)
initial import of CLProgram. Updated JUnit Test accordingly.
Diffstat (limited to 'src')
-rw-r--r--src/com/mbien/opencl/CLContext.java107
-rw-r--r--src/com/mbien/opencl/CLDevice.java17
-rw-r--r--src/com/mbien/opencl/CLException.java6
-rw-r--r--src/com/mbien/opencl/CLPlatform.java11
-rw-r--r--src/com/mbien/opencl/CLProgram.java197
5 files changed, 301 insertions, 37 deletions
diff --git a/src/com/mbien/opencl/CLContext.java b/src/com/mbien/opencl/CLContext.java
index 203172b0..601a2b79 100644
--- a/src/com/mbien/opencl/CLContext.java
+++ b/src/com/mbien/opencl/CLContext.java
@@ -1,18 +1,28 @@
package com.mbien.opencl;
import com.mbien.opencl.impl.CLImpl;
-import com.sun.gluegen.runtime.PointerBuffer;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
import java.nio.IntBuffer;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import static com.mbien.opencl.CLException.*;
+
/**
*
* @author Michael Bien
*/
public final class CLContext {
- private final static CL cl;
+ final static CL cl;
public final long contextID;
+ private CLDevice[] devices;
+
+ private final List<CLProgram> programs;
+
static{
System.loadLibrary("gluegen-rt");
System.loadLibrary("jocl");
@@ -21,45 +31,66 @@ public final class CLContext {
private CLContext(long contextID) {
this.contextID = contextID;
+ this.programs = new ArrayList<CLProgram>();
}
/**
* Creates a default context on all available devices.
*/
- public static CLContext create() {
- IntBuffer ib = IntBuffer.allocate(1);
- long context = cl.clCreateContextFromType(null, 0, CL.CL_DEVICE_TYPE_ALL, null, null, null, 0);
-
-// int errorCode = ib.get();
-// if(errorCode != CL.CL_SUCCESS)
-// throw new CLException(errorCode, "can not create CL context");
-
- return new CLContext(context);
+ public static final CLContext create() {
+ return createContext(CL.CL_DEVICE_TYPE_ALL);
}
/**
* Creates a default context on the specified device types.
*/
- public static CLContext create(CLDevice.Type... deviceTypes) {
+ public static final CLContext create(CLDevice.Type... deviceTypes) {
int type = deviceTypes[0].CL_TYPE;
for (int i = 1; i < deviceTypes.length; i++) {
type |= deviceTypes[i].CL_TYPE;
}
- long ctxID = cl.clCreateContextFromType(null, 0, type, null, null, null, 0);
- return new CLContext(ctxID);
+ return createContext(type);
+ }
+
+ private static final CLContext createContext(long deviceType) {
+
+ IntBuffer error = IntBuffer.allocate(1);
+ long context = cl.clCreateContextFromType(null, 0, deviceType, null, null, error, 0);
+
+ checkForError(error.get(), "can not create CL context");
+
+ return new CLContext(context);
+ }
+
+ public CLProgram createProgram(String src) {
+ CLProgram program = new CLProgram(this, src, contextID);
+ programs.add(program);
+ return program;
+ }
+
+ void programReleased(CLProgram program) {
+ programs.remove(program);
}
/**
* Releases the context and all resources.
*/
- public void release() {
+ public CLContext release() {
int ret = cl.clReleaseContext(contextID);
- if(CL.CL_SUCCESS != ret)
- throw new CLException(ret, "error releasing context");
+ checkForError(ret, "error releasing context");
+ return this;
+ }
+
+ /**
+ * Returns a read only view of all programs associated with this context.
+ */
+ public List<CLProgram> getPrograms() {
+ return Collections.unmodifiableList(programs);
}
+
/**
* Gets the device with maximal FLOPS from this context.
*/
@@ -95,12 +126,45 @@ public final class CLContext {
return null;
}
+*/
+ /**
+ * Returns all devices associated with this CLContext.
+ */
public CLDevice[] getCLDevices() {
+ if(devices == null) {
+
+ int sizeofDeviceID = 8; // TODO doublechek deviceID size on 32 bit systems
+
+ long[] longBuffer = new long[1];
+
+ int ret;
+ ret = cl.clGetContextInfo(contextID, 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(contextID, 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(cl, deviceIDs.getLong()); // TODO doublechek deviceID size on 32 bit systems
+
+ }
+
+ return devices;
}
-*/
+ CLDevice getCLDevices(long dID) {
+ CLDevice[] deviceArray = getCLDevices();
+ for (int i = 0; i < deviceArray.length; i++) {
+ if(dID == deviceArray[i].deviceID)
+ return deviceArray[i];
+ }
+ return null;
+ }
/**
* Lists all available OpenCL implementaitons.
@@ -111,14 +175,12 @@ public final class CLContext {
int[] intBuffer = new int[1];
// find all available OpenCL platforms
int ret = cl.clGetPlatformIDs(0, null, 0, intBuffer, 0);
- if(CL.CL_SUCCESS != ret)
- throw new CLException(ret, "can not enumerate platforms");
+ checkForError(ret, "can not enumerate platforms");
// receive platform ids
long[] platformId = new long[intBuffer[0]];
ret = cl.clGetPlatformIDs(platformId.length, platformId, 0, null, 0);
- if(CL.CL_SUCCESS != ret)
- throw new CLException(ret, "can not enumerate platforms");
+ checkForError(ret, "can not enumerate platforms");
CLPlatform[] platforms = new CLPlatform[platformId.length];
@@ -135,4 +197,5 @@ public final class CLContext {
return cl;
}
+
}
diff --git a/src/com/mbien/opencl/CLDevice.java b/src/com/mbien/opencl/CLDevice.java
index ba20f4b2..d9f643ce 100644
--- a/src/com/mbien/opencl/CLDevice.java
+++ b/src/com/mbien/opencl/CLDevice.java
@@ -7,6 +7,8 @@ import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
+import static com.mbien.opencl.CLException.*;
+
/**
*
* @author Michael Bien
@@ -34,7 +36,7 @@ public final class CLDevice {
*/
DEFAULT(CL.CL_DEVICE_TYPE_DEFAULT);
- /**
+ /**
* Value of wrapped OpenCL device type.
*/
public final int CL_TYPE;
@@ -160,8 +162,7 @@ public final class CLDevice {
int ret = cl.clGetDeviceInfo(deviceID, key, bb.capacity(), bb, null, 0);
- if(CL.CL_SUCCESS != ret)
- throw new CLException(ret, "can not receive device info");
+ checkForError(ret, "can not receive device info");
return bb.getLong();
}
@@ -173,8 +174,7 @@ public final class CLDevice {
int ret = cl.clGetDeviceInfo(deviceID, key, bb.capacity(), bb, longBuffer, 0);
- if(CL.CL_SUCCESS != ret)
- throw new CLException(ret, "can not receive device info string");
+ checkForError(ret, "can not receive device info string");
return new String(bb.array(), 0, (int)longBuffer[0]);
@@ -183,9 +183,10 @@ public final class CLDevice {
@Override
public String toString() {
- return "CLPlatform [name:" + getName()
- + " type:" + getType()
- + " profile: " + getProfile()+"]";
+ return "CLDevice [id: " + deviceID
+ + " name: " + getName()
+ + " type: " + getType()
+ + " profile: " + getProfile()+"]";
}
@Override
diff --git a/src/com/mbien/opencl/CLException.java b/src/com/mbien/opencl/CLException.java
index f439e89b..5806d41d 100644
--- a/src/com/mbien/opencl/CLException.java
+++ b/src/com/mbien/opencl/CLException.java
@@ -22,6 +22,12 @@ public class CLException extends RuntimeException {
super(identifyError(error) + ": " + message);
}
+ public static final void checkForError(int status, String message) {
+ if(status != CL.CL_SUCCESS)
+ throw new CLException(status, message);
+ }
+
+
private static final String identifyError(int error) {
switch (error) {
diff --git a/src/com/mbien/opencl/CLPlatform.java b/src/com/mbien/opencl/CLPlatform.java
index 252872dc..a717564a 100644
--- a/src/com/mbien/opencl/CLPlatform.java
+++ b/src/com/mbien/opencl/CLPlatform.java
@@ -1,7 +1,7 @@
package com.mbien.opencl;
import java.nio.ByteBuffer;
-
+import static com.mbien.opencl.CLException.*;
/**
*
* @author Michael Bien
@@ -29,13 +29,11 @@ public final class CLPlatform {
//find all devices
int ret = cl.clGetDeviceIDs(platformID, CL.CL_DEVICE_TYPE_ALL, 0, null, 0, intBuffer, 0);
- if(CL.CL_SUCCESS != ret)
- throw new CLException(ret, "error while enumerating devices");
+ checkForError(ret, "error while enumerating devices");
long[] deviceIDs = new long[intBuffer[0]];
ret = cl.clGetDeviceIDs(platformID, CL.CL_DEVICE_TYPE_ALL, deviceIDs.length, deviceIDs, 0, null, 0);
- if(CL.CL_SUCCESS != ret)
- throw new CLException(ret, "error while enumerating devices");
+ checkForError(ret, "error while enumerating devices");
CLDevice[] devices = new CLDevice[deviceIDs.length];
@@ -83,8 +81,7 @@ public final class CLPlatform {
ByteBuffer bb = ByteBuffer.allocate(512);
int ret = cl.clGetPlatformInfo(platformID, key, bb.capacity(), bb, longBuffer, 0);
- if(CL.CL_SUCCESS != ret)
- throw new CLException(ret, "can not receive info string");
+ checkForError(ret, "can not receive info string");
return new String(bb.array(), 0, (int)longBuffer[0]);
}
diff --git a/src/com/mbien/opencl/CLProgram.java b/src/com/mbien/opencl/CLProgram.java
new file mode 100644
index 00000000..e93e7246
--- /dev/null
+++ b/src/com/mbien/opencl/CLProgram.java
@@ -0,0 +1,197 @@
+package com.mbien.opencl;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import static com.mbien.opencl.CLException.*;
+
+/**
+ *
+ * @author Michael Bien
+ */
+public class CLProgram {
+
+ private final CLContext context;
+ private final long programID;
+ private final CL cl;
+
+ 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) {
+
+ this.cl = context.cl;
+ this.context = context;
+
+ int[] intArray = new int[1];
+ // Create the program
+ programID = cl.clCreateProgramWithSource(contextID, 1, new String[] {src}, new long[]{src.length()}, 0, intArray, 0);
+ checkForError(intArray[0], "can not create program with source");
+ }
+
+
+ /**
+ * Builds this program for all devices accosiated with the context and implementation specific build options.
+ * @return this
+ */
+ public CLProgram build() {
+ build(null, null);
+ 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.
+ */
+ public CLProgram build(CLDevice[] devices, String options) {
+
+ long[] deviceIDs = null;
+ if(devices != null) {
+ deviceIDs = new long[devices.length];
+ for (int i = 0; i < deviceIDs.length; i++) {
+ deviceIDs[i] = devices[i].deviceID;
+ }
+ }
+
+ // Build the program
+ int ret = cl.clBuildProgram(programID, deviceIDs, options, null, null);
+ checkForError(ret, "error building program");
+
+ return this;
+ }
+
+ /**
+ * Releases this program.
+ * @return this
+ */
+ public CLProgram release() {
+ int ret = cl.clReleaseProgram(programID);
+ checkForError(ret, "can not release program");
+ context.programReleased(this);
+
+ return this;
+ }
+
+ /**
+ * Returns all devices associated with this program.
+ */
+ public CLDevice[] getCLDevices() {
+
+ long[] longArray = new long[1];
+ int ret = cl.clGetProgramInfo(programID, CL.CL_PROGRAM_DEVICES, 0, null, longArray, 0);
+ checkForError(ret, "on clGetProgramInfo");
+
+ ByteBuffer bb = ByteBuffer.allocate((int) longArray[0]).order(ByteOrder.nativeOrder());
+ ret = cl.clGetProgramInfo(programID, CL.CL_PROGRAM_DEVICES, bb.capacity(), bb, null, 0);
+ checkForError(ret, "on clGetProgramInfo");
+
+ int count = bb.capacity() / 8; // TODO sizeof cl_device
+ CLDevice[] devices = new CLDevice[count];
+ for (int i = 0; i < count; i++) {
+ devices[i] = context.getCLDevices(bb.getLong());
+ }
+
+ return devices;
+
+ }
+
+ public String getBuildLog(CLDevice device) {
+ return getBuildInfoString(device.deviceID, CL.CL_PROGRAM_BUILD_LOG);
+ }
+
+ public Status getBuildStatus(CLDevice device) {
+ int clStatus = getBuildInfoInt(device.deviceID, 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.
+ */
+ public String getSource() {
+ return getProgramInfoString(CL.CL_PROGRAM_SOURCE);
+ }
+
+ // TODO binaries, serialization, program build options
+
+ private final String getBuildInfoString(long device, int flag) {
+
+ long[] longArray = new long[1];
+
+ int ret = cl.clGetProgramBuildInfo(programID, device, flag, 0, null, longArray, 0);
+ checkForError(ret, "on clGetProgramBuildInfo");
+
+ ByteBuffer bb = ByteBuffer.allocate((int)longArray[0]).order(ByteOrder.nativeOrder());
+
+ ret = cl.clGetProgramBuildInfo(programID, 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(programID, flag, 0, null, longArray, 0);
+ checkForError(ret, "on clGetProgramInfo");
+
+ ByteBuffer bb = ByteBuffer.allocate((int)longArray[0]).order(ByteOrder.nativeOrder());
+
+ ret = cl.clGetProgramInfo(programID, 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(programID, device, flag, bb.capacity(), bb, null, 0);
+ checkForError(ret, "error on clGetProgramBuildInfo");
+
+ return bb.getInt();
+ }
+
+}