aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Bien <[email protected]>2010-01-18 15:24:29 +0100
committerMichael Bien <[email protected]>2010-01-18 15:24:29 +0100
commit09ac312a0645bd0d9adff580f29f20382dfbf8c9 (patch)
tree52e121e8c366c797f34008244243dd896cc1e88a
parentc4aeea288271f57b3c8640a8cd4ba87d1c331814 (diff)
introduced CLMemory as superclass for all memory objects.
added CLImage, CLImage2d and CLImage3d.
-rw-r--r--resources/cl-if.cfg4
-rw-r--r--resources/clImplCustomCode.java6
-rw-r--r--src/com/mbien/opencl/CLBuffer.java178
-rw-r--r--src/com/mbien/opencl/CLCommandQueue.java4
-rw-r--r--src/com/mbien/opencl/CLContext.java90
-rw-r--r--src/com/mbien/opencl/CLGLContext.java6
-rw-r--r--src/com/mbien/opencl/CLImage.java70
-rw-r--r--src/com/mbien/opencl/CLImage2d.java36
-rw-r--r--src/com/mbien/opencl/CLImage3d.java50
-rw-r--r--src/com/mbien/opencl/CLKernel.java10
-rw-r--r--src/com/mbien/opencl/CLMemory.java208
-rw-r--r--src/com/mbien/opencl/CLPlatform.java45
-rw-r--r--test/com/mbien/opencl/CLBufferTest.java8
-rw-r--r--test/com/mbien/opencl/CLConcurrencyTest.java2
-rw-r--r--test/com/mbien/opencl/HighLevelBindingTest.java14
-rw-r--r--test/com/mbien/opencl/LowLevelBindingTest.java1
16 files changed, 503 insertions, 229 deletions
diff --git a/resources/cl-if.cfg b/resources/cl-if.cfg
index 7a1fa36..9b37973 100644
--- a/resources/cl-if.cfg
+++ b/resources/cl-if.cfg
@@ -19,12 +19,12 @@ Ignore CL_GL_.*|cl.*GL.*
Ignore clCreateContext
CustomJavaCode CL
CustomJavaCode CL /** Interface to C language function: <br> <code> cl_context {@native clCreateContext}(intptr_t * , uint32_t, cl_device_id * , void (*pfn_notify)(const char *, const void *, size_t, void *), void *, int32_t * ); </code> */
-CustomJavaCode CL public long clCreateContext(LongBuffer properties, long[] devices, CreateContextCallback pfn_notify, Object userData, IntBuffer errcode_ret);
+CustomJavaCode CL public long clCreateContext(java.nio.Buffer properties, long[] devices, CreateContextCallback pfn_notify, Object userData, IntBuffer errcode_ret);
Ignore clCreateContextFromType
CustomJavaCode CL
CustomJavaCode CL /** Interface to C language function: <br> <code> cl_context {@native clCreateContextFromType}(cl_context_properties *properties, cl_device_type device_type, void (*pfn_notify)(const char *errinfo, const void *private_info, size_t cb, void *user_data), void *user_data, cl_int *errcode_ret) ; </code> */
-CustomJavaCode CL public long clCreateContextFromType(LongBuffer properties, long device_type, CreateContextCallback pfn_notify, Object userData, IntBuffer errcode_ret);
+CustomJavaCode CL public long clCreateContextFromType(java.nio.Buffer properties, long device_type, CreateContextCallback pfn_notify, Object userData, IntBuffer errcode_ret);
Ignore clBuildProgram
CustomJavaCode CL
diff --git a/resources/clImplCustomCode.java b/resources/clImplCustomCode.java
index cffe9a7..c0c8365 100644
--- a/resources/clImplCustomCode.java
+++ b/resources/clImplCustomCode.java
@@ -1,5 +1,5 @@
- public long clCreateContext(LongBuffer properties, long[] devices, CreateContextCallback pfn_notify, Object userData, IntBuffer errcode_ret) {
+ public long clCreateContext(java.nio.Buffer properties, long[] devices, CreateContextCallback pfn_notify, Object userData, IntBuffer errcode_ret) {
if(pfn_notify != null)
throw new RuntimeException("asynchronous execution with callback is not yet implemented, pass null through this method to block until complete.");
@@ -18,7 +18,7 @@
private native long clCreateContext1(Object cl_context_properties, int props_offset, int deviceCount, long[] devices, CreateContextCallback pfn_notify, Object userData, Object errcode_ret, int err_offset);
- public long clCreateContextFromType(LongBuffer properties, long device_type, CreateContextCallback pfn_notify, Object userData, IntBuffer errcode_ret) {
+ public long clCreateContextFromType(java.nio.Buffer properties, long device_type, CreateContextCallback pfn_notify, Object userData, IntBuffer errcode_ret) {
if(pfn_notify != null)
throw new RuntimeException("asynchronous execution with callback is not yet implemented, pass null through this method to block until complete.");
@@ -61,4 +61,4 @@
values[i-1] = temp>>>32;
values[i ] = temp & 0x00000000FFFFFFFFL;
}
- }
+ }
diff --git a/src/com/mbien/opencl/CLBuffer.java b/src/com/mbien/opencl/CLBuffer.java
index fb63b6e..618cfa9 100644
--- a/src/com/mbien/opencl/CLBuffer.java
+++ b/src/com/mbien/opencl/CLBuffer.java
@@ -1,40 +1,31 @@
package com.mbien.opencl;
-import com.sun.gluegen.runtime.BufferFactory;
import java.nio.Buffer;
-import java.nio.ByteBuffer;
-import java.nio.DoubleBuffer;
-import java.nio.FloatBuffer;
-import java.nio.IntBuffer;
-import java.nio.ShortBuffer;
import static com.mbien.opencl.CLException.*;
-import static com.mbien.opencl.CL.*;
/**
*
* @author Michael Bien
*/
-public class CLBuffer<B extends Buffer> implements CLResource {
+public final class CLBuffer<B extends Buffer> extends CLMemory<B> {
- public final B buffer;
- public final long ID;
-
- private final CLContext context;
- private final CL cl;
- CLBuffer(CLContext context, B directBuffer, int flags) {
- this(context, directBuffer, 0, flags);
+ private CLBuffer(CLContext context, B directBuffer, long id) {
+ super(context, directBuffer, id);
}
- CLBuffer(CLContext context, B directBuffer, int glBuffer, int flags) {
+ static <B extends Buffer> CLBuffer<B> create(CLContext context, B directBuffer, int flags) {
+ return create(context, directBuffer, flags, 0);
+ }
+
+ static <B extends Buffer> CLBuffer<B> create(CLContext context, B directBuffer, int flags, int glBuffer) {
if(!directBuffer.isDirect())
throw new IllegalArgumentException("buffer is not a direct buffer");
- this.buffer = directBuffer;
- this.context = context;
- this.cl = context.cl;
+ CL cl = context.cl;
+ long id;
int[] result = new int[1];
@@ -43,162 +34,23 @@ public class CLBuffer<B extends Buffer> implements CLResource {
if(isHostPointerFlag(flags)) {
host_ptr = directBuffer;
}
- this.ID = cl.clCreateBuffer(context.ID, flags,
- sizeOfBufferElem(directBuffer)*directBuffer.capacity(), host_ptr, result, 0);
+ id = cl.clCreateBuffer(context.ID, flags, sizeOfBufferElem(directBuffer)*directBuffer.capacity(), host_ptr, result, 0);
}else{
if(isHostPointerFlag(flags)) {
throw new IllegalArgumentException(
"CL_MEM_COPY_HOST_PTR or CL_MEM_USE_HOST_PTR can not be used with OpenGL Buffers.");
}
CLGLI clgli = (CLGLI)cl;
- this.ID = clgli.clCreateFromGLBuffer(context.ID, flags, glBuffer, result, 0);
+ id = clgli.clCreateFromGLBuffer(context.ID, flags, glBuffer, result, 0);
}
checkForError(result[0], "can not create cl buffer");
+ return new CLBuffer<B>(context, directBuffer, id);
}
- private final boolean isHostPointerFlag(int flags) {
- return (flags & CL_MEM_COPY_HOST_PTR) != 0 || (flags & CL_MEM_USE_HOST_PTR) != 0;
- }
-
- public void release() {
- int ret = cl.clReleaseMemObject(ID);
- context.onBufferReleased(this);
- checkForError(ret, "can not release mem object");
- }
-
- //stolen from JOGL project... think about merging
- private final int sizeOfBufferElem(Buffer buffer) {
-
- if (buffer instanceof ByteBuffer) {
- return BufferFactory.SIZEOF_BYTE;
- } else if (buffer instanceof IntBuffer) {
- return BufferFactory.SIZEOF_INT;
- } else if (buffer instanceof ShortBuffer) {
- return BufferFactory.SIZEOF_SHORT;
- } else if (buffer instanceof FloatBuffer) {
- return BufferFactory.SIZEOF_FLOAT;
- } else if (buffer instanceof DoubleBuffer) {
- return BufferFactory.SIZEOF_DOUBLE;
- }
- throw new RuntimeException("Unexpected buffer type " + buffer.getClass().getName());
- }
-
- int getSizeInBytes() {
- return sizeOfBufferElem(buffer)*buffer.capacity();
- }
-
-
@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
- * written by a kernel.
- */
- READ_WRITE(CL_MEM_READ_WRITE),
-
- /**
- * 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_MEM_WRITE_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_MEM_READ_ONLY),
-
- /**
- * Enum representing CL.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_MEM_USE_HOST_PTR),
-
-// ALLOC_HOST_PTR(CL_MEM_ALLOC_HOST_PTR), // this is the default in java world anyway
-
- /**
- * Enum representing CL.CL_MEM_COPY_HOST_PTR.
- * If CL_MEM_COPY_HOST_PTR 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.
- */
- COPY_BUFFER(CL_MEM_COPY_HOST_PTR);
-
- /**
- * Value of wrapped OpenCL flag.
- */
- public final int CONFIG;
-
- private Mem(int config) {
- this.CONFIG = config;
- }
-
- public static Mem valueOf(int bufferFlag) {
- switch(bufferFlag) {
- case(CL_MEM_READ_WRITE):
- return READ_WRITE;
- case(CL_MEM_READ_ONLY):
- return READ_ONLY;
- case(CL_MEM_USE_HOST_PTR):
- return USE_BUFFER;
-// case(CL_MEM_ALLOC_HOST_PTR):
-// return ALLOC_HOST_PTR;
- case(CL_MEM_COPY_HOST_PTR):
- return COPY_BUFFER;
- }
- return null;
- }
-
- static int flagsToInt(Mem[] flags) {
- int clFlags = 0;
- if(flags != null) {
- for (int i = 0; i < flags.length; i++) {
- clFlags |= flags[i].CONFIG;
- }
- }
- if(clFlags == 0)
- clFlags = CL_MEM_READ_WRITE;
- return clFlags;
- }
-
+ public <T extends Buffer> CLBuffer<T> cloneWith(T directBuffer) {
+ return new CLBuffer<T>(context, directBuffer, ID);
}
}
diff --git a/src/com/mbien/opencl/CLCommandQueue.java b/src/com/mbien/opencl/CLCommandQueue.java
index 06308f0..bc50210 100644
--- a/src/com/mbien/opencl/CLCommandQueue.java
+++ b/src/com/mbien/opencl/CLCommandQueue.java
@@ -55,7 +55,7 @@ public class CLCommandQueue implements CLResource {
int ret = cl.clEnqueueWriteBuffer(
ID, writeBuffer.ID, blockingWrite ? CL_TRUE : CL_FALSE,
- 0, writeBuffer.getSizeInBytes(), writeBuffer.buffer,
+ 0, writeBuffer.getSize(), writeBuffer.buffer,
0, null, events==null ? null : events.IDs);
if(ret != CL_SUCCESS)
@@ -77,7 +77,7 @@ public class CLCommandQueue implements CLResource {
int ret = cl.clEnqueueReadBuffer(
ID, readBuffer.ID, blockingRead ? CL_TRUE : CL_FALSE,
- 0, readBuffer.getSizeInBytes(), readBuffer.buffer,
+ 0, readBuffer.getSize(), readBuffer.buffer,
0, null, events==null ? null : events.IDs);
if(ret != CL_SUCCESS)
diff --git a/src/com/mbien/opencl/CLContext.java b/src/com/mbien/opencl/CLContext.java
index a272fbc..3db9be2 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.CLMemory.Mem;
import com.mbien.opencl.CLSampler.AddressingMode;
import com.mbien.opencl.CLSampler.FilteringMode;
import com.sun.gluegen.runtime.CPU;
@@ -40,7 +40,7 @@ public class CLContext implements CLResource {
protected final List<CLProgram> programs;
protected final List<CLSampler> samplers;
- protected final List<CLBuffer<? extends Buffer>> buffers;
+ protected final List<CLMemory<? extends Buffer>> memoryObjects;
protected final Map<CLDevice, List<CLCommandQueue>> queuesMap;
@@ -49,7 +49,7 @@ public class CLContext implements CLResource {
this.ID = contextID;
this.programs = new ArrayList<CLProgram>();
this.samplers = new ArrayList<CLSampler>();
- this.buffers = new ArrayList<CLBuffer<? extends Buffer>>();
+ this.memoryObjects = new ArrayList<CLMemory<? extends Buffer>>();
this.queuesMap = new HashMap<CLDevice, List<CLCommandQueue>>();
}
@@ -79,7 +79,8 @@ public class CLContext implements CLResource {
* The platform to be used is implementation dependent.
*/
public static final CLContext create() {
- return new CLContext(createContextFromType(null, CL.CL_DEVICE_TYPE_ALL));
+ Buffer properties = setupContextProperties(null);
+ return new CLContext(createContextFromType(properties, CL.CL_DEVICE_TYPE_ALL));
}
/**
@@ -118,13 +119,7 @@ public class CLContext implements CLResource {
}
}
- LongBuffer properties = null;
- if(platform != null) {
- properties = LongBuffer.allocate(3);
- properties.put(CL.CL_CONTEXT_PLATFORM).put(platform.ID).put(0); // 0 terminated array
- properties.rewind();
- }
-
+ Buffer properties = setupContextProperties(platform);
return new CLContext(createContextFromType(properties, type));
}
@@ -140,17 +135,11 @@ public class CLContext implements CLResource {
deviceIDs[i] = devices[i].ID;
}
- LongBuffer properties = null;
- if(platform != null) {
- properties = LongBuffer.allocate(3);
- properties.put(CL.CL_CONTEXT_PLATFORM).put(platform.ID).put(0); // 0 terminated array
- properties.rewind();
- }
-
+ Buffer properties = setupContextProperties(platform);
return new CLContext(createContext(properties, deviceIDs));
}
- protected static final long createContextFromType(LongBuffer properties, long deviceType) {
+ protected static final long createContextFromType(Buffer properties, long deviceType) {
IntBuffer status = IntBuffer.allocate(1);
long context = CLPlatform.getLowLevelBinding().clCreateContextFromType(properties, deviceType, null, null, status);
@@ -160,7 +149,7 @@ public class CLContext implements CLResource {
return context;
}
- protected static final long createContext(LongBuffer properties, long[] devices) {
+ protected static final long createContext(Buffer properties, long[] devices) {
IntBuffer status = IntBuffer.allocate(1);
long context = CLPlatform.getLowLevelBinding().clCreateContext(properties, devices, null, null, status);
@@ -170,6 +159,31 @@ public class CLContext implements CLResource {
return context;
}
+ private static final Buffer setupContextProperties(CLPlatform platform) {
+
+ if(platform == null) {
+ CLPlatform[] platforms = CLPlatform.listCLPlatforms();
+ if(platforms.length > 0)
+ platform = platforms[0];
+ }
+// System.out.println(platform.ID);
+// System.out.println((int)platform.ID);
+
+ Buffer properties = null;
+ if(platform != null) {
+ if(CPU.is32Bit()){
+ int id = (int)platform.ID;// (int)(platform.ID & 0x00000000FFFFFFFFL);
+ properties = ByteBuffer.allocate(4*3).order(ByteOrder.nativeOrder())
+ .putInt(CL.CL_CONTEXT_PLATFORM).putInt(id).putInt(0); // 0 terminated array
+ }else{
+ properties = LongBuffer.allocate(3)
+ .put(CL.CL_CONTEXT_PLATFORM).put(platform.ID).put(0); // 0 terminated array
+ }
+ properties.rewind();
+ }
+ return properties;
+ }
+
/**
* Creates a program from the given sources, the program is not build yet.
*/
@@ -262,8 +276,8 @@ public class CLContext implements CLResource {
* Creates a CLBuffer with the specified flags.
*/
public final <B extends Buffer> CLBuffer<B> createBuffer(B directBuffer, int flags) {
- CLBuffer<B> buffer = new CLBuffer<B>(this, directBuffer, flags);
- buffers.add(buffer);
+ CLBuffer<B> buffer = CLBuffer.create(this, directBuffer, flags);
+ memoryObjects.add(buffer);
return buffer;
}
@@ -291,8 +305,8 @@ public class CLContext implements CLResource {
programs.remove(program);
}
- void onBufferReleased(CLBuffer<?> buffer) {
- buffers.remove(buffer);
+ void onMemoryReleased(CLMemory<?> buffer) {
+ memoryObjects.remove(buffer);
}
void onCommandQueueReleased(CLDevice device, CLCommandQueue queue) {
@@ -316,8 +330,8 @@ public class CLContext implements CLResource {
while(!programs.isEmpty())
programs.get(0).release();
- while(!buffers.isEmpty())
- buffers.get(0).release();
+ while(!memoryObjects.isEmpty())
+ memoryObjects.get(0).release();
while(!samplers.isEmpty())
samplers.get(0).release();
@@ -343,23 +357,39 @@ public class CLContext implements CLResource {
}
/**
- * Returns a read only view of all buffers associated with this context.
+ * Returns a read only view of all allocated memory objects associated with this context.
*/
- public List<CLBuffer<? extends Buffer>> getCLBuffers() {
- return Collections.unmodifiableList(buffers);
+ public List<CLMemory<? extends Buffer>> getCLMemoryObjects() {
+ return Collections.unmodifiableList(memoryObjects);
}
+ /**
+ * Returns a read only view of all samplers associated with this context.
+ */
+ public List<CLSampler> getCLSamplers() {
+ return Collections.unmodifiableList(samplers);
+ }
/**
- * Gets the device with maximal FLOPS from this context.
+ * Returns 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.
+ * @see #getMaxFlopsDevice(com.mbien.opencl.CLDevice.Type)
*/
public CLDevice getMaxFlopsDevice() {
return CLPlatform.findMaxFlopsDevice(getCLDevices());
}
/**
+ * Returns the device with maximal FLOPS and the specified type from this context.
+ * The device speed is estimated by calulating the product of
+ * MAX_COMPUTE_UNITS and MAX_CLOCK_FREQUENCY.
+ */
+ public CLDevice getMaxFlopsDevice(CLDevice.Type type) {
+ return CLPlatform.findMaxFlopsDevice(getCLDevices(), type);
+ }
+
+ /**
* Returns all devices associated with this CLContext.
*/
public CLDevice[] getCLDevices() {
diff --git a/src/com/mbien/opencl/CLGLContext.java b/src/com/mbien/opencl/CLGLContext.java
index f3edae7..6336dfc 100644
--- a/src/com/mbien/opencl/CLGLContext.java
+++ b/src/com/mbien/opencl/CLGLContext.java
@@ -1,7 +1,7 @@
package com.mbien.opencl;
import java.nio.Buffer;
-import com.mbien.opencl.CLBuffer.Mem;
+import com.mbien.opencl.CLMemory.Mem;
import com.sun.opengl.impl.GLContextImpl;
import com.sun.opengl.impl.macosx.cgl.MacOSXCGLContext;
import com.sun.opengl.impl.windows.wgl.WindowsWGLContext;
@@ -81,8 +81,8 @@ public final class CLGLContext extends CLContext {
}
public final <B extends Buffer> CLBuffer<B> createFromGLBuffer(B directBuffer, int glBuffer, int flags) {
- CLBuffer<B> buffer = new CLBuffer<B>(this, directBuffer, glBuffer, flags);
- buffers.add(buffer);
+ CLBuffer<B> buffer = CLBuffer.create(this, directBuffer, flags, glBuffer);
+ memoryObjects.add(buffer);
return buffer;
}
diff --git a/src/com/mbien/opencl/CLImage.java b/src/com/mbien/opencl/CLImage.java
new file mode 100644
index 0000000..448caed
--- /dev/null
+++ b/src/com/mbien/opencl/CLImage.java
@@ -0,0 +1,70 @@
+package com.mbien.opencl;
+
+import com.sun.gluegen.runtime.PointerBuffer;
+import java.nio.Buffer;
+
+import static com.mbien.opencl.CL.*;
+
+/**
+ *
+ * @author Michael Bien
+ */
+public abstract class CLImage<B extends Buffer> extends CLMemory<B> {
+
+ protected final CLImageFormat format;
+
+ final CLInfoAccessor imageInfo;
+
+ protected CLImage(CLContext context, B directBuffer, CLImageFormat format, long id) {
+ super(context, directBuffer, id);
+ this.imageInfo = new CLImageInfoAccessor();
+ this.format = format;
+ }
+
+ /**
+ * Returns the image format descriptor specified when image was created.
+ */
+ public CLImageFormat getFormat() {
+ return format;
+ }
+
+ /**
+ * Returns the size of each element of the image memory object given by image.
+ * An element is made up of n channels. The value of n is given in {@link CLImageFormat} descriptor.
+ */
+ public int getElementSize() {
+ return (int)imageInfo.getLong(CL_IMAGE_ELEMENT_SIZE);
+ }
+
+ /**
+ * Returns the size in bytes of a row of elements of the image object given by image.
+ */
+ public int getRowPitch() {
+ return (int)imageInfo.getLong(CL_IMAGE_ROW_PITCH);
+ }
+
+ /**
+ * Returns width of this image in pixels.
+ */
+ public int getWidth() {
+ return (int)imageInfo.getLong(CL_IMAGE_WIDTH);
+ }
+
+ /**
+ * Returns the height of this image in pixels.
+ */
+ public int getHeight() {
+ return (int)imageInfo.getLong(CL_IMAGE_HEIGHT);
+ }
+
+
+
+ private final class CLImageInfoAccessor extends CLInfoAccessor {
+ @Override
+ protected int getInfo(int name, long valueSize, Buffer value, PointerBuffer valueSizeRet) {
+ return cl.clGetImageInfo(ID, name, valueSize, value, valueSizeRet);
+ }
+ }
+
+
+}
diff --git a/src/com/mbien/opencl/CLImage2d.java b/src/com/mbien/opencl/CLImage2d.java
new file mode 100644
index 0000000..ca8b58e
--- /dev/null
+++ b/src/com/mbien/opencl/CLImage2d.java
@@ -0,0 +1,36 @@
+package com.mbien.opencl;
+
+import com.sun.gluegen.runtime.BufferFactory;
+import java.nio.Buffer;
+import java.nio.IntBuffer;
+
+import static com.mbien.opencl.CLException.*;
+
+/**
+ *
+ * @author Michael Bien
+ */
+public final class CLImage2d<B extends Buffer> extends CLImage<B> {
+
+ private CLImage2d(CLContext context, B directBuffer, CLImageFormat format, long id) {
+ super(context, directBuffer, format, id);
+ }
+
+ static <B extends Buffer> CLImage2d<B> createImage(CLContext context, B directBuffer,
+ int width, int height, int rowPitch, CLImageFormat format, int flags) {
+
+ CL cl = context.cl;
+ IntBuffer err = BufferFactory.newDirectByteBuffer(4).asIntBuffer();
+
+ long id = cl.clCreateImage2D(context.ID, flags, format, width, height, rowPitch, directBuffer, err);
+ checkForError(err.get(), "can not create 2d image");
+
+ return new CLImage2d<B>(context, directBuffer, format, id);
+ }
+
+ @Override
+ public <T extends Buffer> CLImage2d<T> cloneWith(T directBuffer) {
+ return new CLImage2d<T>(context, directBuffer, format, ID);
+ }
+
+}
diff --git a/src/com/mbien/opencl/CLImage3d.java b/src/com/mbien/opencl/CLImage3d.java
new file mode 100644
index 0000000..c0928a4
--- /dev/null
+++ b/src/com/mbien/opencl/CLImage3d.java
@@ -0,0 +1,50 @@
+package com.mbien.opencl;
+
+import com.sun.gluegen.runtime.BufferFactory;
+import java.nio.Buffer;
+import java.nio.IntBuffer;
+
+import static com.mbien.opencl.CL.*;
+import static com.mbien.opencl.CLException.*;
+
+/**
+ *
+ * @author Michael Bien
+ */
+public final class CLImage3d<B extends Buffer> extends CLImage<B> {
+
+ private CLImage3d(CLContext context, B directBuffer, CLImageFormat format, long id) {
+ super(context, directBuffer, format, id);
+ }
+
+ static <B extends Buffer> CLImage3d<B> createImage(CLContext context, B directBuffer,
+ int width, int height, int depth, int rowPitch, int slicePitch, CLImageFormat format, int flags) {
+
+ 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);
+ checkForError(err.get(), "can not create 2d image");
+
+ return new CLImage3d<B>(context, directBuffer, format, id);
+ }
+
+ @Override
+ public <T extends Buffer> CLImage3d<T> cloneWith(T directBuffer) {
+ return new CLImage3d<T>(context, directBuffer, format, ID);
+ }
+
+ /**
+ * Returns the size in bytes of a 2D slice of this 3D image.
+ */
+ public int getSlicePitch() {
+ return (int)imageInfo.getLong(CL_IMAGE_SLICE_PITCH);
+ }
+
+ /**
+ * Returns the depth of this image in pixels.
+ */
+ public int getDepth() {
+ return (int)imageInfo.getLong(CL_IMAGE_DEPTH);
+ }
+}
diff --git a/src/com/mbien/opencl/CLKernel.java b/src/com/mbien/opencl/CLKernel.java
index 30ccc20..33d3073 100644
--- a/src/com/mbien/opencl/CLKernel.java
+++ b/src/com/mbien/opencl/CLKernel.java
@@ -58,7 +58,7 @@ public class CLKernel implements CLResource {
}
- public CLKernel putArg(CLBuffer<?> value) {
+ public CLKernel putArg(CLMemory<?> value) {
setArg(argIndex++, value);
return this;
}
@@ -83,13 +83,13 @@ public class CLKernel implements CLResource {
return this;
}
- public CLKernel putArgs(CLBuffer<?>... values) {
+ public CLKernel putArgs(CLMemory<?>... values) {
setArgs(argIndex, values);
argIndex += values.length;
return this;
}
- public CLKernel setArg(int argumentIndex, CLBuffer<?> value) {
+ public CLKernel setArg(int argumentIndex, CLMemory<?> value) {
setArgument(argumentIndex, CPU.is32Bit()?4:8, wrap(value.ID));
return this;
}
@@ -114,12 +114,12 @@ public class CLKernel implements CLResource {
return this;
}
- public CLKernel setArgs(CLBuffer<?>... values) {
+ public CLKernel setArgs(CLMemory<?>... values) {
setArgs(0, values);
return this;
}
- private final void setArgs(int startIndex, CLBuffer<?>... values) {
+ private final void setArgs(int startIndex, CLMemory<?>... values) {
for (int i = 0; i < values.length; i++) {
setArg(i+startIndex, values[i]);
}
diff --git a/src/com/mbien/opencl/CLMemory.java b/src/com/mbien/opencl/CLMemory.java
new file mode 100644
index 0000000..86ad66d
--- /dev/null
+++ b/src/com/mbien/opencl/CLMemory.java
@@ -0,0 +1,208 @@
+package com.mbien.opencl;
+
+import com.sun.gluegen.runtime.BufferFactory;
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+import java.nio.DoubleBuffer;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.nio.ShortBuffer;
+
+import static com.mbien.opencl.CLException.*;
+
+/**
+ *
+ * @author Michael Bien
+ */
+public abstract class CLMemory <B extends Buffer> implements CLResource {
+
+ B buffer;
+
+ public final long ID;
+
+ protected final CLContext context;
+ protected final CL cl;
+
+ protected <Buffer> CLMemory(CLContext context, long id) {
+ this.context = context;
+ this.cl = context.cl;
+ this.ID = id;
+ }
+
+ protected CLMemory(CLContext context, B directBuffer, long id) {
+ this.buffer = directBuffer;
+ this.context = context;
+ this.cl = context.cl;
+ this.ID = id;
+ }
+
+ protected static final boolean isHostPointerFlag(int flags) {
+ return (flags & CL.CL_MEM_COPY_HOST_PTR) != 0 || (flags & CL.CL_MEM_USE_HOST_PTR) != 0;
+ }
+
+ protected static final int sizeOfBufferElem(Buffer buffer) {
+ if (buffer instanceof ByteBuffer) {
+ return BufferFactory.SIZEOF_BYTE;
+ } else if (buffer instanceof IntBuffer) {
+ return BufferFactory.SIZEOF_INT;
+ } else if (buffer instanceof ShortBuffer) {
+ return BufferFactory.SIZEOF_SHORT;
+ } else if (buffer instanceof FloatBuffer) {
+ return BufferFactory.SIZEOF_FLOAT;
+ } else if (buffer instanceof DoubleBuffer) {
+ return BufferFactory.SIZEOF_DOUBLE;
+ }
+ throw new RuntimeException("Unexpected buffer type " + buffer.getClass().getName());
+ }
+
+ /**
+ * Returns a new instance of CLMemory pointing to the same CLResource but using a different Buffer.
+ */
+ public abstract <T extends Buffer> CLMemory<T> cloneWith(T directBuffer);
+
+
+ public CLMemory<B> use(B buffer) {
+ if(this.buffer != null && buffer != null && this.buffer.getClass() != buffer.getClass()) {
+ throw new IllegalArgumentException(
+ "expected a Buffer of class " + this.buffer.getClass()
+ +" but got " + buffer.getClass());
+ }
+ this.buffer = buffer;
+ return this;
+ }
+
+ public B getBuffer() {
+ return buffer;
+ }
+
+ /**
+ * Returns the size of the wrapped direct buffer in byte.
+ */
+ public int getSize() {
+ if(buffer == null) {
+ return 0;
+ }
+ return sizeOfBufferElem(buffer) * buffer.capacity();
+ }
+
+ public void release() {
+ int ret = cl.clReleaseMemObject(ID);
+ context.onMemoryReleased(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 CLMemory<?> other = (CLMemory<?>) obj;
+ if (this.ID != other.ID) {
+ return false;
+ }
+ if (this.context != other.context && (this.context == null || !this.context.equals(other.context))) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 83 * hash + (int) (this.ID ^ (this.ID >>> 32));
+ hash = 83 * hash + (this.context != null ? this.context.hashCode() : 0);
+ return hash;
+ }
+
+ /**
+ * Memory settings for configuring CLMemory.
+ */
+ public enum Mem {
+
+ /**
+ * This flag specifies that the memory object will be read and
+ * written by a kernel.
+ */
+ READ_WRITE(CL.CL_MEM_READ_WRITE),
+
+ /**
+ * 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),
+
+ /**
+ * 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),
+
+ /**
+ * Enum representing CL.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),
+
+// ALLOC_HOST_PTR(CL_MEM_ALLOC_HOST_PTR), // this is the default in java world anyway
+
+ /**
+ * Enum representing CL.CL_MEM_COPY_HOST_PTR.
+ * If CL_MEM_COPY_HOST_PTR 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.
+ */
+ COPY_BUFFER(CL.CL_MEM_COPY_HOST_PTR);
+
+ /**
+ * Value of wrapped OpenCL flag.
+ */
+ public final int CONFIG;
+
+ private Mem(int config) {
+ this.CONFIG = config;
+ }
+
+ public static Mem valueOf(int bufferFlag) {
+ switch (bufferFlag) {
+ case CL.CL_MEM_READ_WRITE:
+ return Mem.READ_WRITE;
+ case CL.CL_MEM_READ_ONLY:
+ return Mem.READ_ONLY;
+ case CL.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:
+ return Mem.COPY_BUFFER;
+ }
+ return null;
+ }
+
+ static int flagsToInt(Mem[] flags) {
+ int clFlags = 0;
+ if (flags != null) {
+ for (int i = 0; i < flags.length; i++) {
+ clFlags |= flags[i].CONFIG;
+ }
+ }
+ if (clFlags == 0) {
+ clFlags = CL.CL_MEM_READ_WRITE;
+ }
+ return clFlags;
+ }
+ }
+
+
+
+}
diff --git a/src/com/mbien/opencl/CLPlatform.java b/src/com/mbien/opencl/CLPlatform.java
index 6b17b01..f669cb0 100644
--- a/src/com/mbien/opencl/CLPlatform.java
+++ b/src/com/mbien/opencl/CLPlatform.java
@@ -62,17 +62,25 @@ public final class CLPlatform {
/**
* Lists all physical devices available on this platform.
+ * @see #listCLDevices(com.mbien.opencl.CLDevice.Type)
*/
public CLDevice[] listCLDevices() {
+ return this.listCLDevices(CLDevice.Type.ALL);
+ }
+
+ /**
+ * Lists all physical devices available on this platform matching the given {@link CLDevice.Type}.
+ */
+ public CLDevice[] listCLDevices(CLDevice.Type type) {
int[] intBuffer = new int[1];
//find all devices
- int ret = cl.clGetDeviceIDs(ID, CL_DEVICE_TYPE_ALL, 0, null, 0, intBuffer, 0);
+ int ret = cl.clGetDeviceIDs(ID, type.TYPE, 0, null, 0, intBuffer, 0);
checkForError(ret, "error while enumerating devices");
long[] deviceIDs = new long[intBuffer[0]];
- ret = cl.clGetDeviceIDs(ID, CL_DEVICE_TYPE_ALL, deviceIDs.length, deviceIDs, 0, null, 0);
+ ret = cl.clGetDeviceIDs(ID, type.TYPE, deviceIDs.length, deviceIDs, 0, null, 0);
checkForError(ret, "error while enumerating devices");
CLDevice[] devices = new CLDevice[deviceIDs.length];
@@ -86,6 +94,10 @@ public final class CLPlatform {
}
static final CLDevice findMaxFlopsDevice(CLDevice[] devices) {
+ return findMaxFlopsDevice(devices, null);
+ }
+
+ static final CLDevice findMaxFlopsDevice(CLDevice[] devices, CLDevice.Type type) {
CLDevice maxFLOPSDevice = null;
@@ -94,14 +106,19 @@ public final class CLPlatform {
for (int i = 0; i < devices.length; i++) {
CLDevice device = devices[i];
- int maxComputeUnits = device.getMaxComputeUnits();
- int maxClockFrequency = device.getMaxClockFrequency();
- int flops = maxComputeUnits*maxClockFrequency;
- if(flops > maxflops) {
- maxflops = flops;
- maxFLOPSDevice = device;
+ if(type == null || type.equals(device.getType())) {
+
+ int maxComputeUnits = device.getMaxComputeUnits();
+ int maxClockFrequency = device.getMaxClockFrequency();
+ int flops = maxComputeUnits*maxClockFrequency;
+
+ if(flops > maxflops) {
+ maxflops = flops;
+ maxFLOPSDevice = device;
+ }
}
+
}
return maxFLOPSDevice;
@@ -109,15 +126,25 @@ public final class CLPlatform {
/**
- * Gets the device with maximal FLOPS from this platform.
+ * Returns the device with maximal FLOPS from this platform.
* The device speed is estimated by calulating the product of
* MAX_COMPUTE_UNITS and MAX_CLOCK_FREQUENCY.
+ * @see #getMaxFlopsDevice(com.mbien.opencl.CLDevice.Type)
*/
public CLDevice getMaxFlopsDevice() {
return findMaxFlopsDevice(listCLDevices());
}
/**
+ * Returns the device with maximal FLOPS and the specified type from this platform.
+ * The device speed is estimated by calulating the product of
+ * MAX_COMPUTE_UNITS and MAX_CLOCK_FREQUENCY.
+ */
+ public CLDevice getMaxFlopsDevice(CLDevice.Type type) {
+ return findMaxFlopsDevice(listCLDevices(type));
+ }
+
+ /**
* Returns the platform name.
*/
public String getName() {
diff --git a/test/com/mbien/opencl/CLBufferTest.java b/test/com/mbien/opencl/CLBufferTest.java
index 5395ef6..c6b8729 100644
--- a/test/com/mbien/opencl/CLBufferTest.java
+++ b/test/com/mbien/opencl/CLBufferTest.java
@@ -1,6 +1,6 @@
package com.mbien.opencl;
-import com.mbien.opencl.CLBuffer.Mem;
+import com.mbien.opencl.CLMemory.Mem;
import com.sun.opengl.util.BufferUtil;
import java.nio.ByteBuffer;
import org.junit.Test;
@@ -77,11 +77,11 @@ public class CLBufferTest {
.putReadBuffer(clBufferB, true) // read B
.finish();
- assertEquals(2, context.getCLBuffers().size());
+ assertEquals(2, context.getCLMemoryObjects().size());
clBufferA.release();
- assertEquals(1, context.getCLBuffers().size());
+ assertEquals(1, context.getCLMemoryObjects().size());
clBufferB.release();
- assertEquals(0, context.getCLBuffers().size());
+ assertEquals(0, context.getCLMemoryObjects().size());
// uploading worked when a==b.
out.println("validating computed results...");
diff --git a/test/com/mbien/opencl/CLConcurrencyTest.java b/test/com/mbien/opencl/CLConcurrencyTest.java
index dfaa4e4..bcd290a 100644
--- a/test/com/mbien/opencl/CLConcurrencyTest.java
+++ b/test/com/mbien/opencl/CLConcurrencyTest.java
@@ -1,6 +1,6 @@
package com.mbien.opencl;
-import com.mbien.opencl.CLBuffer.Mem;
+import com.mbien.opencl.CLMemory.Mem;
import java.io.IOException;
import java.nio.ByteBuffer;
import org.junit.Test;
diff --git a/test/com/mbien/opencl/HighLevelBindingTest.java b/test/com/mbien/opencl/HighLevelBindingTest.java
index 84c2a33..d28dd04 100644
--- a/test/com/mbien/opencl/HighLevelBindingTest.java
+++ b/test/com/mbien/opencl/HighLevelBindingTest.java
@@ -1,6 +1,6 @@
package com.mbien.opencl;
-import com.mbien.opencl.CLBuffer.Mem;
+import com.mbien.opencl.CLMemory.Mem;
import com.mbien.opencl.CLCommandQueue.Mode;
import com.mbien.opencl.CLDevice.FPConfig;
import java.io.IOException;
@@ -169,17 +169,17 @@ public class HighLevelBindingTest {
out.print(dest.getInt()+", ");
out.println("...; "+dest.remaining()/SIZEOF_INT + " more");
- assertTrue(3 == context.getCLBuffers().size());
+ assertTrue(3 == context.getCLMemoryObjects().size());
clBufferA.release();
- assertTrue(2 == context.getCLBuffers().size());
+ assertTrue(2 == context.getCLMemoryObjects().size());
- assertTrue(2 == context.getCLBuffers().size());
+ assertTrue(2 == context.getCLMemoryObjects().size());
clBufferB.release();
- assertTrue(1 == context.getCLBuffers().size());
+ assertTrue(1 == context.getCLMemoryObjects().size());
- assertTrue(1 == context.getCLBuffers().size());
+ assertTrue(1 == context.getCLMemoryObjects().size());
clBufferC.release();
- assertTrue(0 == context.getCLBuffers().size());
+ assertTrue(0 == context.getCLMemoryObjects().size());
assertTrue(1 == context.getCLPrograms().size());
diff --git a/test/com/mbien/opencl/LowLevelBindingTest.java b/test/com/mbien/opencl/LowLevelBindingTest.java
index 94b86e7..f802185 100644
--- a/test/com/mbien/opencl/LowLevelBindingTest.java
+++ b/test/com/mbien/opencl/LowLevelBindingTest.java
@@ -186,6 +186,7 @@ public class LowLevelBindingTest {
int ret = CL.CL_SUCCESS;
int[] intArray = new int[1];
+ //TODO properties not allowed to be null
long context = cl.clCreateContextFromType(null, CL.CL_DEVICE_TYPE_ALL, null, null, null);
out.println("context handle: "+context);