diff options
author | Michael Bien <[email protected]> | 2010-01-18 15:24:29 +0100 |
---|---|---|
committer | Michael Bien <[email protected]> | 2010-01-18 15:24:29 +0100 |
commit | 09ac312a0645bd0d9adff580f29f20382dfbf8c9 (patch) | |
tree | 52e121e8c366c797f34008244243dd896cc1e88a | |
parent | c4aeea288271f57b3c8640a8cd4ba87d1c331814 (diff) |
introduced CLMemory as superclass for all memory objects.
added CLImage, CLImage2d and CLImage3d.
-rw-r--r-- | resources/cl-if.cfg | 4 | ||||
-rw-r--r-- | resources/clImplCustomCode.java | 6 | ||||
-rw-r--r-- | src/com/mbien/opencl/CLBuffer.java | 178 | ||||
-rw-r--r-- | src/com/mbien/opencl/CLCommandQueue.java | 4 | ||||
-rw-r--r-- | src/com/mbien/opencl/CLContext.java | 90 | ||||
-rw-r--r-- | src/com/mbien/opencl/CLGLContext.java | 6 | ||||
-rw-r--r-- | src/com/mbien/opencl/CLImage.java | 70 | ||||
-rw-r--r-- | src/com/mbien/opencl/CLImage2d.java | 36 | ||||
-rw-r--r-- | src/com/mbien/opencl/CLImage3d.java | 50 | ||||
-rw-r--r-- | src/com/mbien/opencl/CLKernel.java | 10 | ||||
-rw-r--r-- | src/com/mbien/opencl/CLMemory.java | 208 | ||||
-rw-r--r-- | src/com/mbien/opencl/CLPlatform.java | 45 | ||||
-rw-r--r-- | test/com/mbien/opencl/CLBufferTest.java | 8 | ||||
-rw-r--r-- | test/com/mbien/opencl/CLConcurrencyTest.java | 2 | ||||
-rw-r--r-- | test/com/mbien/opencl/HighLevelBindingTest.java | 14 | ||||
-rw-r--r-- | test/com/mbien/opencl/LowLevelBindingTest.java | 1 |
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); |