diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/com/mbien/opencl/CLContext.java | 11 | ||||
-rw-r--r-- | src/com/mbien/opencl/CLException.java | 11 | ||||
-rw-r--r-- | src/com/mbien/opencl/CLProgram.java | 66 | ||||
-rw-r--r-- | src/com/mbien/opencl/InternalBufferUtil.java | 39 | ||||
-rw-r--r-- | src/com/mbien/opencl/QueueBarrier.java | 2 |
5 files changed, 117 insertions, 12 deletions
diff --git a/src/com/mbien/opencl/CLContext.java b/src/com/mbien/opencl/CLContext.java index 6fbad0df..19e3ef09 100644 --- a/src/com/mbien/opencl/CLContext.java +++ b/src/com/mbien/opencl/CLContext.java @@ -214,6 +214,13 @@ public class CLContext implements CLResource { return createProgram(sb.toString()); } + + public CLProgram createProgram(Map<CLDevice, byte[]> binaries) { + CLProgram program = new CLProgram(this, binaries); + programs.add(program); + return program; + } + /** * Creates a CLBuffer with the specified flags and element count. No flags creates a MEM.READ_WRITE buffer. */ @@ -379,8 +386,8 @@ public class CLContext implements CLResource { } /** - * Returns the device with maximal FLOPS and the specified type from this context. - * The device speed is estimated by calulating the product of + * Returns the device with maximal FLOPS of the specified device type from this context. + * The device speed is estimated by calculating the product of * MAX_COMPUTE_UNITS and MAX_CLOCK_FREQUENCY. */ public CLDevice getMaxFlopsDevice(CLDevice.Type type) { diff --git a/src/com/mbien/opencl/CLException.java b/src/com/mbien/opencl/CLException.java index 35c539c4..3703f235 100644 --- a/src/com/mbien/opencl/CLException.java +++ b/src/com/mbien/opencl/CLException.java @@ -3,7 +3,7 @@ package com.mbien.opencl; import static com.mbien.opencl.CL.*; /** - * Main Exception type for runtime OpenCL errors and unsuccessful function calls (e.g. returning other values than CL_SUCCESS). + * Main Exception type for runtime OpenCL errors and unsuccessful function calls (e.g. returning not CL_SUCCESS). * @author Michael Bien */ public class CLException extends RuntimeException { @@ -17,11 +17,20 @@ public class CLException extends RuntimeException { errorcode = error; } + /** + * Throws a CLException when <code>status != CL_SUCCESS</code>. + */ public static final void checkForError(int status, String message) { if(status != CL_SUCCESS) throw new CLException(status, message); } + /** + * Returns a human readable String for the OpenCL error code. + */ + public String getCLErrorString() { + return identifyError(errorcode); + } private static final String identifyError(int error) { diff --git a/src/com/mbien/opencl/CLProgram.java b/src/com/mbien/opencl/CLProgram.java index 9e141dde..306a5b66 100644 --- a/src/com/mbien/opencl/CLProgram.java +++ b/src/com/mbien/opencl/CLProgram.java @@ -1,5 +1,6 @@ package com.mbien.opencl; +import com.sun.gluegen.runtime.BufferFactory; import com.sun.gluegen.runtime.CPU; import com.sun.gluegen.runtime.PointerBuffer; import java.nio.ByteBuffer; @@ -11,6 +12,7 @@ import java.util.Map; import static com.mbien.opencl.CLException.*; import static com.mbien.opencl.CL.*; +import java.util.Set; /** * @@ -33,18 +35,55 @@ public class CLProgram implements CLResource { this.cl = context.cl; this.context = context; - IntBuffer ib = ByteBuffer.allocateDirect(4).order(ByteOrder.nativeOrder()).asIntBuffer(); + IntBuffer ib = BufferFactory.newDirectByteBuffer(4).asIntBuffer(); // Create the program ID = cl.clCreateProgramWithSource(context.ID, 1, new String[] {src}, PointerBuffer.allocateDirect(1).put(src.length()), ib); checkForError(ib.get(), "can not create program with source"); } + CLProgram(CLContext context, Map<CLDevice, byte[]> binaries) { + + this.cl = context.cl; + this.context = context; + + PointerBuffer devices = PointerBuffer.allocateDirect(binaries.size()); + PointerBuffer lengths = PointerBuffer.allocateDirect(binaries.size()); + ByteBuffer[] codeBuffers = new ByteBuffer[binaries.size()]; + + int i = 0; + Set<CLDevice> keys = binaries.keySet(); + for (CLDevice device : keys) { + + byte[] bytes = binaries.get(device); + + devices.put(device.ID); + lengths.put(bytes.length); + + codeBuffers[i] = BufferFactory.newDirectByteBuffer(bytes.length).put(bytes); + codeBuffers[i].rewind(); + i++; + } + devices.rewind(); + lengths.rewind(); + + IntBuffer err = BufferFactory.newDirectByteBuffer(4).asIntBuffer(); +// IntBuffer status = BufferFactory.newDirectByteBuffer(binaries.size()*4).asIntBuffer(); + ID = cl.clCreateProgramWithBinary(context.ID, devices.capacity(), devices, lengths, codeBuffers, /*status*/null, err); + +// while(status.remaining() != 0) { +// checkForError(status.get(), "unable to load binaries on all devices"); +// } + + checkForError(err.get(), "can not create program with binary"); + + } + private final void initKernels() { if(kernels == null) { - IntBuffer numKernels = ByteBuffer.allocateDirect(4).order(ByteOrder.nativeOrder()).asIntBuffer(); + IntBuffer numKernels = BufferFactory.newDirectByteBuffer(4).asIntBuffer(); int ret = cl.clCreateKernelsInProgram(ID, 0, null, numKernels); checkForError(ret, "can not create kernels for program"); @@ -348,16 +387,27 @@ public class CLProgram implements CLResource { int ret = cl.clGetProgramInfo(ID, CL_PROGRAM_BINARY_SIZES, sizes.capacity(), sizes, null); checkForError(ret, "on clGetProgramInfo"); - int binarySize = 0; - while(sizes.remaining() != 0) - binarySize += (int)sizes.getLong(); + int binariesSize = 0; + while(sizes.remaining() != 0) { + int size = (int) sizes.getLong(); + binariesSize += size; + } + ByteBuffer binaries = ByteBuffer.allocateDirect(binariesSize).order(ByteOrder.nativeOrder()); - ByteBuffer binaries = ByteBuffer.allocateDirect(binarySize).order(ByteOrder.nativeOrder()); - ret = cl.clGetProgramInfo(ID, CL_PROGRAM_BINARIES, binaries.capacity(), binaries, null); // TODO crash, driver bug? + + long address = InternalBufferUtil.getDirectBufferAddress(binaries); + PointerBuffer addresses = PointerBuffer.allocateDirect(sizes.capacity()); + sizes.rewind(); + while(sizes.remaining() != 0) { + addresses.put(address); + address += sizes.getLong(); + } + + ret = cl.clGetProgramInfo(ID, CL_PROGRAM_BINARIES, addresses.capacity(), addresses.getBuffer(), null); checkForError(ret, "on clGetProgramInfo"); Map<CLDevice, byte[]> map = new HashMap<CLDevice, byte[]>(); - + sizes.rewind(); for (int i = 0; i < devices.length; i++) { byte[] bytes = new byte[(int)sizes.getLong()]; binaries.get(bytes); diff --git a/src/com/mbien/opencl/InternalBufferUtil.java b/src/com/mbien/opencl/InternalBufferUtil.java new file mode 100644 index 00000000..a2573784 --- /dev/null +++ b/src/com/mbien/opencl/InternalBufferUtil.java @@ -0,0 +1,39 @@ +package com.mbien.opencl; + +import java.lang.reflect.Field; +import java.nio.Buffer; +import sun.misc.Unsafe; + +/** + * + * @author Michael Bien + */ +class InternalBufferUtil { + + private static final long addressFieldOffset; + private static Unsafe unsafe; + + static { + try { + Field f = Buffer.class.getDeclaredField("address"); + + Field[] fields = Unsafe.class.getDeclaredFields(); + for (int i = 0; i < fields.length; i++) { + if (fields[i].getName().equals("theUnsafe")) { + fields[i].setAccessible(true); + unsafe = (Unsafe)fields[i].get(Unsafe.class); + break; + } + } + + addressFieldOffset = unsafe.objectFieldOffset(f); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static long getDirectBufferAddress(Buffer buffer) { + return ((buffer == null) ? 0 : unsafe.getLong(buffer, addressFieldOffset)); + } + +}
\ No newline at end of file diff --git a/src/com/mbien/opencl/QueueBarrier.java b/src/com/mbien/opencl/QueueBarrier.java index d3a5ab2e..73339192 100644 --- a/src/com/mbien/opencl/QueueBarrier.java +++ b/src/com/mbien/opencl/QueueBarrier.java @@ -67,7 +67,7 @@ public class QueueBarrier { } /** - * @see {@link #await()} + * @see #await() * @param timeout the maximum time to wait * @param unit the time unit of the {@code timeout} argument */ |