diff options
-rw-r--r-- | resources/clImplCustomCode.c | 60 | ||||
-rw-r--r-- | resources/clImplCustomCode.java | 23 | ||||
-rw-r--r-- | src/com/mbien/opencl/CLContext.java | 61 | ||||
-rw-r--r-- | src/com/mbien/opencl/CLDevice.java | 22 | ||||
-rw-r--r-- | test/com/mbien/opencl/LowLevelBindingTest.java | 53 |
5 files changed, 179 insertions, 40 deletions
diff --git a/resources/clImplCustomCode.c b/resources/clImplCustomCode.c index a35328dc..57d1c3e3 100644 --- a/resources/clImplCustomCode.c +++ b/resources/clImplCustomCode.c @@ -52,40 +52,64 @@ Java_com_mbien_opencl_impl_CLImpl_clCreateContextFromType1(JNIEnv *env, jobject return (jlong)_ctx; } - /* + * Entry point to C language function: + *extern CL_API_ENTRY cl_context CL_API_CALL + *clCreateContext(cl_context_properties * properties , + * cl_uint num_devices , + * const cl_device_id * devices , + * void (*pfn_notify)(const char *, const void *, size_t, void *) pfn_notify , + * void * user_data , + * cl_int * errcode_ret ) CL_API_SUFFIX__VERSION_1_0; + */ JNIEXPORT jlong JNICALL -Java_com_mbien_opencl_impl_CLImpl_clCreateContext0(JNIEnv *env, jobject _unused, - jobject props, jint props_byte_offset, jlong device_type, jobject cb, jobject data, jobject errcode, jint errcode_byte_offset) { +Java_com_mbien_opencl_impl_CLImpl_clCreateContext1(JNIEnv *env, jobject _unused, + jobject props, jint props_byte_offset, jint numDevices, jobject deviceList, jobject cb, jobject data, jobject errcode, jint errcode_byte_offset) { intptr_t * _props_ptr = NULL; int32_t * _errcode_ptr = NULL; - void * _device_ptr = NULL; + size_t * _deviceListPtr = NULL; - cl_context _res; + cl_context _ctx; if (props != NULL) { - _props_ptr = (intptr_t *) (((char*) (*env)->GetDirectBufferAddress(env, props)) + props_byte_offset); + _props_ptr = (void *) (((char*) (*env)->GetPrimitiveArrayCritical(env, props, NULL)) + props_byte_offset); + } + if (deviceList != NULL) { + _deviceListPtr = (void *) (((char*) (*env)->GetPrimitiveArrayCritical(env, deviceList, NULL)) /*+ device_byte_offset*/); + } + if (errcode != NULL) { + _errcode_ptr = (void *) (((char*) (*env)->GetPrimitiveArrayCritical(env, errcode, NULL)) + errcode_byte_offset); } - if (device_type != NULL) { - _device_ptr = (void *) (((char*) (*env)->GetPrimitiveArrayCritical(env, device_type, NULL))); - } + // TODO payload, callback... + _ctx = clCreateContext((cl_context_properties *) _props_ptr, numDevices, (cl_device_id *)_deviceListPtr, NULL, NULL, (int32_t *) _errcode_ptr); - _res = clCreateContext(); + if (errcode != NULL) { + (*env)->ReleasePrimitiveArrayCritical(env, errcode, _errcode_ptr, 0); + } + if (deviceList != NULL) { + (*env)->ReleasePrimitiveArrayCritical(env, deviceList, _deviceListPtr, 0); + } + if (props != NULL) { + (*env)->ReleasePrimitiveArrayCritical(env, props, _props_ptr, 0); + } - if (device_type != NULL) { - (*env)->ReleasePrimitiveArrayCritical(env, device_type, _device_ptr, 0); - } - return (jlong) (intptr_t) _res; + return (jlong) _ctx; } -*/ /** - * Entry point to C language function: <code> int32_t clBuildProgram(cl_program, uint32_t, cl_device_id * , const char * , void (*pfn_notify)(cl_program, void *user_data), void * ); + * Entry point to C language function: + * extern CL_API_ENTRY cl_int CL_API_CALL + *clBuildProgram(cl_program program , + * cl_uint num_devices , + * const cl_device_id * device_list , + * const char * options , + * void (*pfn_notify)(cl_program program , void * user_data ), + * void * user_data ) CL_API_SUFFIX__VERSION_1_0; */ JNIEXPORT jint JNICALL -Java_com_mbien_opencl_impl_CLImpl_clBuildProgram0(JNIEnv *env, jobject _unused, +Java_com_mbien_opencl_impl_CLImpl_clBuildProgram1(JNIEnv *env, jobject _unused, jlong program, jint deviceCount, jobject deviceList, jint offset, jstring options, jobject cb, jobject data) { const char* _strchars_options = NULL; @@ -106,7 +130,7 @@ Java_com_mbien_opencl_impl_CLImpl_clBuildProgram0(JNIEnv *env, jobject _unused, } // TODO payload, callback... - _res = clBuildProgram((cl_program)program, (cl_uint)deviceCount, _deviceListPtr, _strchars_options, NULL, NULL); + _res = clBuildProgram((cl_program)program, (cl_uint)deviceCount, (cl_device_id *)_deviceListPtr, _strchars_options, NULL, NULL); if (deviceList != NULL) { (*env)->ReleasePrimitiveArrayCritical(env, deviceList, _deviceListPtr, 0); diff --git a/resources/clImplCustomCode.java b/resources/clImplCustomCode.java index 0d25ddb6..d74d5b82 100644 --- a/resources/clImplCustomCode.java +++ b/resources/clImplCustomCode.java @@ -1,10 +1,21 @@ - public long clCreateContext(IntBuffer properties, long[] devices, CreateContextCallback cb, Object userData, IntBuffer errcode_ret) { + public long clCreateContext(IntBuffer properties, long[] devices, CreateContextCallback pfn_notify, Object userData, IntBuffer errcode_ret) { - throw new RuntimeException("not yet implemented, use clCreateContextFromType instead"); -// return this.clCreateContext0(properties, offset1, devices, cb, null, errcode_ret, offset2); + if(pfn_notify != null) + throw new RuntimeException("asynchronous execution with callback is not yet implemented, pass null through this method to block until complete."); + + if(userData != null) + System.err.println("WARNING: userData not yet implemented... ignoring"); + + int listLength = 0; + if(devices != null) + listLength = devices.length; + + return this.clCreateContext1( + BufferFactory.getArray(properties), BufferFactory.getIndirectBufferByteOffset(properties), listLength, devices, null, null, + BufferFactory.getArray(errcode_ret), BufferFactory.getIndirectBufferByteOffset(errcode_ret) ); } - private native long clCreateContext0(Object cl_context_properties, int props_offset, long[] devices, CreateContextCallback pfn_notify, Object userData, Object errcode_ret, int err_offset); + 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(IntBuffer properties, long device_type, CreateContextCallback pfn_notify, Object userData, IntBuffer errcode_ret) { @@ -35,8 +46,8 @@ if(deviceList != null) listLength = deviceList.length; - return clBuildProgram0(program, listLength, deviceList, 0, options, cb, userData); + return clBuildProgram1(program, listLength, deviceList, 0, options, cb, userData); } /** Entry point to C language function: <code> int32_t clBuildProgram(cl_program, uint32_t, cl_device_id * , const char * , void * ); </code> */ - private native int clBuildProgram0(long program, int devices, Object deviceList, int arg2_byte_offset, String options, BuildProgramCallback cb, Object userData); + private native int clBuildProgram1(long program, int devices, Object deviceList, int arg2_byte_offset, String options, BuildProgramCallback cb, Object userData); diff --git a/src/com/mbien/opencl/CLContext.java b/src/com/mbien/opencl/CLContext.java index 81ac58f0..68ff131c 100644 --- a/src/com/mbien/opencl/CLContext.java +++ b/src/com/mbien/opencl/CLContext.java @@ -66,29 +66,44 @@ public final class CLContext { } /** - * Creates a default context on all available devices (CL_DEVICE_TYPE_ALL). + * Creates a context on all available devices (CL_DEVICE_TYPE_ALL). * The platform to be used is implementation dependent. */ public static final CLContext create() { - return createContext(null, CL.CL_DEVICE_TYPE_ALL); + return createContextFromType(null, CL.CL_DEVICE_TYPE_ALL); } /** - * Creates a default context on the specified device types. + * Creates a context on the specified device types. * The platform to be used is implementation dependent. */ public static final CLContext create(CLDevice.Type... deviceTypes) { return create(null, deviceTypes); } + /** + * Creates a context on the specified devices. + * The platform to be used is implementation dependent. + */ + public static final CLContext create(CLDevice... devices) { + return create(null, devices); + } + + /** + * Creates a context on the specified platform on all available devices (CL_DEVICE_TYPE_ALL). + */ + public static final CLContext create(CLPlatform platform) { + return create(platform, CLDevice.Type.ALL); + } + // TODO check if driver bug, otherwise find the reason why this is not working (INVALID_VALUE with NV driver) /** - * Creates a default context on the specified platform and with the specified + * Creates a context on the specified platform and with the specified * device types. */ private static final CLContext create(CLPlatform platform, CLDevice.Type... deviceTypes) { - int type = 0; + long type = 0; if(deviceTypes != null) { for (int i = 0; i < deviceTypes.length; i++) { type |= deviceTypes[i].CL_TYPE; @@ -102,10 +117,32 @@ public final class CLContext { properties.rewind(); } - return createContext(properties, type); + return createContextFromType(properties, type); + } + + /** + * Creates a context on the specified platform and with the specified + * devices. + */ + private static final CLContext create(CLPlatform platform, CLDevice... devices) { + + long[] deviceIDs = new long[devices.length]; + + for (int i = 0; i < devices.length; i++) { + deviceIDs[i] = devices[i].ID; + } + + IntBuffer properties = null; + if(platform != null) { + properties = IntBuffer.allocate(3); + properties.put(CL.CL_CONTEXT_PLATFORM).put((int)platform.ID).put(0); // TODO check if this has to be int or long + properties.rewind(); + } + + return createContext(properties, deviceIDs); } - private static final CLContext createContext(IntBuffer properties, long deviceType) { + private static final CLContext createContextFromType(IntBuffer properties, long deviceType) { IntBuffer status = IntBuffer.allocate(1); long context = CLPlatform.getLowLevelBinding().clCreateContextFromType(properties, deviceType, null, null, status); @@ -115,6 +152,16 @@ public final class CLContext { return new CLContext(context); } + private static final CLContext createContext(IntBuffer properties, long[] devices) { + + IntBuffer status = IntBuffer.allocate(1); + long context = CLPlatform.getLowLevelBinding().clCreateContext(properties, devices, null, null, status); + + checkForError(status.get(), "can not create CL context"); + + return new CLContext(context); + } + /** * Creates a program from the given sources, the program is not build yet. */ diff --git a/src/com/mbien/opencl/CLDevice.java b/src/com/mbien/opencl/CLDevice.java index 0ad8f0e9..de49aafa 100644 --- a/src/com/mbien/opencl/CLDevice.java +++ b/src/com/mbien/opencl/CLDevice.java @@ -255,21 +255,31 @@ public final class CLDevice { */ ACCELERATOR(CL.CL_DEVICE_TYPE_ACCELERATOR), /** - * CL_DEVICE_TYPE_DEFAULT + * CL_DEVICE_TYPE_DEFAULT. This type can be used for creating a context on + * the default device, a single device can never have this type. */ - DEFAULT(CL.CL_DEVICE_TYPE_DEFAULT); + DEFAULT(CL.CL_DEVICE_TYPE_DEFAULT), + /** + * CL_DEVICE_TYPE_ALL. This type can be used for creating a context on + * all devices, a single device can never have this type. + */ + ALL(CL.CL_DEVICE_TYPE_ALL); /** * Value of wrapped OpenCL device type. */ - public final int CL_TYPE; + public final long CL_TYPE; - private Type(int CL_TYPE) { + private Type(long CL_TYPE) { this.CL_TYPE = CL_TYPE; } - public static Type valueOf(int clDeviceType) { - switch(clDeviceType) { + public static Type valueOf(long clDeviceType) { + + if(clDeviceType == CL.CL_DEVICE_TYPE_ALL) + return ALL; + + switch((int)clDeviceType) { case(CL.CL_DEVICE_TYPE_DEFAULT): return DEFAULT; case(CL.CL_DEVICE_TYPE_CPU): diff --git a/test/com/mbien/opencl/LowLevelBindingTest.java b/test/com/mbien/opencl/LowLevelBindingTest.java index 3776a349..bff9db36 100644 --- a/test/com/mbien/opencl/LowLevelBindingTest.java +++ b/test/com/mbien/opencl/LowLevelBindingTest.java @@ -3,6 +3,7 @@ package com.mbien.opencl; import com.sun.gluegen.runtime.CPU; import java.nio.ByteBuffer; import java.nio.ByteOrder; +import java.nio.IntBuffer; import java.util.Arrays; import org.junit.BeforeClass; import org.junit.Test; @@ -47,7 +48,7 @@ public class LowLevelBindingTest { } @Test - public void lowLevelTest1() { + public void contextlessTest() { out.println(" - - - lowLevelTest; contextless binding - - - "); @@ -118,7 +119,53 @@ public class LowLevelBindingTest { } @Test - public void lowLevelTest2() { + public void createContextTest() { + + out.println(" - - - createContextTest - - - "); + + CL cl = CLPlatform.getLowLevelBinding(); + + int[] intArray = new int[1]; + // find all available OpenCL platforms + int ret = cl.clGetPlatformIDs(0, null, 0, intArray, 0); + checkForError(ret); + out.println("#platforms: "+intArray[0]); + + long[] longArray = new long[intArray[0]]; + ret = cl.clGetPlatformIDs(longArray.length, longArray, 0, null, 0); + checkForError(ret); + + long platform = longArray[0]; + + //find all devices + ret = cl.clGetDeviceIDs(platform, CL.CL_DEVICE_TYPE_ALL, 0, null, 0, intArray, 0); + checkForError(ret); + out.println("#devices: "+intArray[0]); + + long[] devices = new long[intArray[0]]; + ret = cl.clGetDeviceIDs(platform, CL.CL_DEVICE_TYPE_ALL, devices.length, devices, 0, null, 0); + + IntBuffer intBuffer = IntBuffer.allocate(1); + long context = cl.clCreateContext(null, devices, null, null, intBuffer); + checkError("on clCreateContext", intBuffer.get()); + + //get number of devices + ret = cl.clGetContextInfo(context, CL.CL_CONTEXT_DEVICES, 0, null, longArray, 0); + checkError("on clGetContextInfo", ret); + + int sizeofLong = (CPU.is32Bit()?4:8); + out.println("context created with " + longArray[0]/sizeofLong + " devices"); + + //check if equal + assertEquals("context was not created on all devices specified", devices.length, longArray[0]/sizeofLong); + + ret = cl.clReleaseContext(context); + checkError("on clReleaseContext", ret); + } + + + @Test + public void lowLevelVectorAddTest() { out.println(" - - - lowLevelTest2; VectorAdd kernel - - - "); @@ -295,7 +342,7 @@ public class LowLevelBindingTest { out.println(" - - - loadTest - - - "); for(int i = 0; i < 100; i++) { out.println("###iteration "+i); - lowLevelTest2(); + lowLevelVectorAddTest(); } } |