diff options
-rw-r--r-- | resources/cl-common.cfg | 1 | ||||
-rw-r--r-- | resources/cl-if.cfg | 7 | ||||
-rw-r--r-- | resources/cl-impl.cfg | 3 | ||||
-rw-r--r-- | resources/clImplCustomCode.c | 66 | ||||
-rw-r--r-- | src/com/jogamp/opencl/CLEvent.java | 19 | ||||
-rw-r--r-- | src/com/jogamp/opencl/CLEventListener.java | 15 | ||||
-rw-r--r-- | src/com/jogamp/opencl/impl/CLEventCallback.java | 15 | ||||
-rw-r--r-- | src/com/jogamp/opencl/impl/CLImpl.java | 11 | ||||
-rw-r--r-- | test/com/jogamp/opencl/CLCommandQueueTest.java | 40 |
9 files changed, 167 insertions, 10 deletions
diff --git a/resources/cl-common.cfg b/resources/cl-common.cfg index c5cf4f62..f9c32c84 100644 --- a/resources/cl-common.cfg +++ b/resources/cl-common.cfg @@ -108,5 +108,4 @@ TagNativeBinding true Ignore .*APPLE.* # TODO implement custom callbacks if this makes sense -Ignore clSetEventCallback Ignore clSetMemObjectDestructorCallback diff --git a/resources/cl-if.cfg b/resources/cl-if.cfg index 6f19e64f..b8deb126 100644 --- a/resources/cl-if.cfg +++ b/resources/cl-if.cfg @@ -6,7 +6,8 @@ Style InterfaceOnly Import java.nio.IntBuffer Import java.nio.LongBuffer Import com.jogamp.opencl.impl.CLImageFormatImpl -import com.jogamp.opencl.impl.BuildProgramCallback; +import com.jogamp.opencl.impl.BuildProgramCallback +import com.jogamp.opencl.impl.CLEventCallback ClassJavadoc CL /** ClassJavadoc CL * Java bindings to OpenCL, the Open Computing Language. @@ -33,6 +34,10 @@ CustomJavaCode CL CustomJavaCode CL /** Interface to C language function: <br> <code> int32_t {@native clBuildProgram}(cl_program, uint32_t, cl_device_id * , const char * , void (*pfn_notify)(cl_program, void *user_data), void * ); </code> */ CustomJavaCode CL public int clBuildProgram(long program, int deviceCount, PointerBuffer devices, String options, BuildProgramCallback cb); +Ignore clSetEventCallback +CustomJavaCode CL +CustomJavaCode CL public int clSetEventCallback(long event, int type, CLEventCallback listener); + Ignore clEnqueueNativeKernel #TODO.. diff --git a/resources/cl-impl.cfg b/resources/cl-impl.cfg index f42b814c..f3367eac 100644 --- a/resources/cl-impl.cfg +++ b/resources/cl-impl.cfg @@ -72,6 +72,9 @@ ForceProcAddressGen clEnqueueNativeKernel Ignore clReleaseContext ForceProcAddressGen clReleaseContext +Ignore clSetEventCallback +ForceProcAddressGen clSetEventCallback + #take buffer capacity from input param 5 ReturnValueCapacity clEnqueueMapBuffer {5} diff --git a/resources/clImplCustomCode.c b/resources/clImplCustomCode.c index 89b350ec..bf4cf1c9 100644 --- a/resources/clImplCustomCode.c +++ b/resources/clImplCustomCode.c @@ -9,8 +9,10 @@ void checkStatus(const char* msg, int status) { JavaVM * jvm; -jmethodID bcb_mid; -jmethodID cccb_mid; +jmethodID buildCB_mid; +jmethodID contextCB_mid; +jmethodID eventCB_mid; +jmethodID memObjCB_mid; JNIEXPORT jint JNICALL @@ -26,14 +28,22 @@ JNI_OnLoad(JavaVM * _jvm, void *reserved) { // throws ClassNotFoundException (or other reflection stuff) jclass buildCBClassID = (*env)->FindClass(env, "com/jogamp/opencl/impl/BuildProgramCallback"); jclass errorHandlerClassID = (*env)->FindClass(env, "com/jogamp/opencl/CLErrorHandler"); + jclass eventCBClassID = (*env)->FindClass(env, "com/jogamp/opencl/impl/CLEventCallback"); + jclass memObjCBClassID = (*env)->FindClass(env, "com/jogamp/opencl/CLMemObjectDestructorCallback"); // throws even more reflection Exceptions // IDs are unique and do not change if (buildCBClassID != NULL) { - bcb_mid = (*env)->GetMethodID(env, buildCBClassID, "buildFinished", "(J)V"); + buildCB_mid = (*env)->GetMethodID(env, buildCBClassID, "buildFinished", "(J)V"); } if (errorHandlerClassID != NULL) { - cccb_mid = (*env)->GetMethodID(env, errorHandlerClassID, "onError", "(Ljava/lang/String;Ljava/nio/ByteBuffer;J)V"); + contextCB_mid = (*env)->GetMethodID(env, errorHandlerClassID, "onError", "(Ljava/lang/String;Ljava/nio/ByteBuffer;J)V"); + } + if (eventCBClassID != NULL) { + eventCB_mid = (*env)->GetMethodID(env, eventCBClassID, "eventStateChanged", "(JI)V"); + } + if (memObjCBClassID != NULL) { + memObjCB_mid = (*env)->GetMethodID(env, memObjCBClassID, "memoryDeallocated", "(Lcom/jogamp/opencl/CLMemory;)V"); } return JNI_VERSION_1_2; @@ -43,6 +53,8 @@ JNI_OnLoad(JavaVM * _jvm, void *reserved) { // callbacks typedef void (CL_CALLBACK * cccallback)(const char *, const void *, size_t, void *); typedef void (CL_CALLBACK * bpcallback)(cl_program, void *); +typedef void (CL_CALLBACK * evcallback)(cl_event, cl_int, void *); +typedef void (CL_CALLBACK * mocallback)(cl_mem, void *); CL_CALLBACK void buildProgramCallback(cl_program id, void * object) { @@ -51,7 +63,7 @@ CL_CALLBACK void buildProgramCallback(cl_program id, void * object) { (*jvm)->AttachCurrentThread(jvm, (void **)&env, NULL); - (*env)->CallVoidMethod(env, obj, bcb_mid, (jlong)(intptr_t)id); + (*env)->CallVoidMethod(env, obj, buildCB_mid, (jlong)(intptr_t)id); (*env)->DeleteGlobalRef(env, obj); (*jvm)->DetachCurrentThread(jvm); @@ -68,12 +80,35 @@ CL_CALLBACK void createContextCallback(const char * errinfo, const void * privat jstring errorString = (*env)->NewStringUTF(env, errinfo); //TODO private_info - (*env)->CallVoidMethod(env, obj, cccb_mid, errorString, NULL, 0); + (*env)->CallVoidMethod(env, obj, contextCB_mid, errorString, NULL, 0); (*jvm)->DetachCurrentThread(jvm); } +CL_CALLBACK void eventCallback(cl_event event, cl_int status, void * object) { + + JNIEnv *env; + jobject obj = (jobject)object; + + (*jvm)->AttachCurrentThread(jvm, (void **)&env, NULL); + + (*env)->CallVoidMethod(env, obj, eventCB_mid, event, status); + (*env)->DeleteGlobalRef(env, obj); // events can only fire once + + (*jvm)->DetachCurrentThread(jvm); +} +/* +CL_CALLBACK void memObjDestructorCallback(cl_mem mem, void * object) { + + JNIEnv *env; + jobject obj = (jobject)object; + + (*jvm)->AttachCurrentThread(jvm, (void **)&env, NULL); + + (*jvm)->DetachCurrentThread(jvm); +} +*/ /* Java->C glue code: * Java package: com.jogamp.opencl.impl.CLImpl @@ -338,4 +373,21 @@ Java_com_jogamp_opencl_impl_CLImpl_clEnqueueMapImage0__JJIJLjava_lang_Object_2IL } return (*env)->NewDirectByteBuffer(env, _res, pixels * (*elements)); -}
\ No newline at end of file + +} + +JNIEXPORT jint JNICALL +Java_com_jogamp_opencl_impl_CLImpl_clSetEventCallback0(JNIEnv *env, jobject _unused, + jlong event, jint trigger, jobject listener, jlong procAddress) { + + cl_event _event = event; + cl_int _trigger = trigger; + cl_int _res; + typedef int32_t (*function)(cl_event, cl_int, void (*pfn_event_notify) (cl_event, cl_int, void *), void *); + function clSetEventCallback = (function)(intptr_t) procAddress; + + jobject cb = (*env)->NewGlobalRef(env, listener); + _res = (*clSetEventCallback)(_event, _trigger, &eventCallback, cb); + + return _res; +} diff --git a/src/com/jogamp/opencl/CLEvent.java b/src/com/jogamp/opencl/CLEvent.java index b7df1465..8423e7c6 100644 --- a/src/com/jogamp/opencl/CLEvent.java +++ b/src/com/jogamp/opencl/CLEvent.java @@ -1,7 +1,10 @@ package com.jogamp.opencl; +import com.jogamp.opencl.impl.CLEventCallback; +import java.util.List; import com.jogamp.common.nio.PointerBuffer; import java.nio.Buffer; +import java.util.ArrayList; import static com.jogamp.opencl.CL.*; import static com.jogamp.opencl.CLException.*; @@ -25,6 +28,22 @@ public class CLEvent extends CLObject implements CLResource { this.eventProfilingInfo = new CLEventProfilingInfoAccessor(); } + /** + * Registers a callback which will be called when the event terminates (COMPLETE or ERROR). + */ + public void registerCallback(final CLEventListener callback) { + this.registerCallback(callback, ExecutionStatus.COMPLETE); + } + + // apparently only ExecutionStatus.COMPLETE is allowed -> private + private void registerCallback(final CLEventListener callback, ExecutionStatus trigger) { + cl.clSetEventCallback(ID, trigger.STATUS, new CLEventCallback() { + public void eventStateChanged(long event, int status) { + callback.eventStateChanged(CLEvent.this, status); + } + }); + } + public void release() { int ret = cl.clReleaseEvent(ID); checkForError(ret, "can not release event"); diff --git a/src/com/jogamp/opencl/CLEventListener.java b/src/com/jogamp/opencl/CLEventListener.java new file mode 100644 index 00000000..76911008 --- /dev/null +++ b/src/com/jogamp/opencl/CLEventListener.java @@ -0,0 +1,15 @@ +/* + * Created on Thursday, September 02 2010 22:01 + */ +package com.jogamp.opencl; + +/** + * A callback for a specific command execution status. + * @author Michael Bien + * @see CLEvent#registerCallback(com.jogamp.opencl.CLEventListener) + */ +public interface CLEventListener { + + public void eventStateChanged(CLEvent event, int status); + +}
\ No newline at end of file diff --git a/src/com/jogamp/opencl/impl/CLEventCallback.java b/src/com/jogamp/opencl/impl/CLEventCallback.java new file mode 100644 index 00000000..db4d5b35 --- /dev/null +++ b/src/com/jogamp/opencl/impl/CLEventCallback.java @@ -0,0 +1,15 @@ +/* + * Created on Tuesday, July 06 2010 00:46 + */ + +package com.jogamp.opencl.impl; + +/** + * A callback for a specific command execution status. + * @author Michael Bien + */ +public interface CLEventCallback { + + public void eventStateChanged(long event, int status); + +} diff --git a/src/com/jogamp/opencl/impl/CLImpl.java b/src/com/jogamp/opencl/impl/CLImpl.java index abec3597..b9dd9835 100644 --- a/src/com/jogamp/opencl/impl/CLImpl.java +++ b/src/com/jogamp/opencl/impl/CLImpl.java @@ -123,6 +123,17 @@ public class CLImpl extends CLAbstractImpl { /** 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 deviceCount, Object deviceList, int deviceListOffset, String options, BuildProgramCallback cb, long address); + + public int clSetEventCallback(long event, int trigger, CLEventCallback callback) { + final long address = addressTable._addressof_clSetEventCallback; + if (address == 0) { + throw new UnsupportedOperationException("Method not available"); + } + return clSetEventCallback0(event, trigger, callback, address); + } + + private native int clSetEventCallback0(long event, int type, CLEventCallback cb, long address); + /** Interface to C language function: <br> <code> void * {@native clEnqueueMapImage}(cl_command_queue command_queue, cl_mem image, uint32_t blocking_map, uint64_t map_flags, const size_t * , const size_t * , size_t * image_row_pitch, size_t * image_slice_pitch, uint32_t num_events_in_wait_list, cl_event * event_wait_list, cl_event * event, int32_t * errcode_ret); </code> @param origin a direct {@link com.jogamp.common.nio.PointerBuffer} @param range a direct {@link com.jogamp.common.nio.PointerBuffer} diff --git a/test/com/jogamp/opencl/CLCommandQueueTest.java b/test/com/jogamp/opencl/CLCommandQueueTest.java index 9c4cc7a8..cafdbc18 100644 --- a/test/com/jogamp/opencl/CLCommandQueueTest.java +++ b/test/com/jogamp/opencl/CLCommandQueueTest.java @@ -1,11 +1,13 @@ package com.jogamp.opencl; +import java.util.concurrent.CountDownLatch; import com.jogamp.opencl.util.MultiQueueBarrier; import com.jogamp.opencl.CLCommandQueue.Mode; import com.jogamp.opencl.CLMemory.Mem; import java.io.IOException; import java.nio.ByteBuffer; import java.util.EnumSet; +import java.util.concurrent.TimeUnit; import org.junit.Test; import static org.junit.Assert.*; @@ -172,7 +174,6 @@ public class CLCommandQueueTest { final int elements = roundUp(groupSize, ONE_MB / SIZEOF_INT * 5); // 5MB per buffer - // 5MB per buffer CLPlatform[] platforms = CLPlatform.listCLPlatforms(); CLPlatform theChosenOne = platforms[0]; for (CLPlatform platform : platforms) { @@ -247,6 +248,43 @@ public class CLCommandQueueTest { } @Test + public void eventCallbackTest() throws InterruptedException { + + out.println(" - - - event callback test - - - "); + + CLPlatform platform = CLPlatform.getDefault(); + + if(!platform.isAtLeast(CL_1_1)) { + out.println("test dissabled, required CLVersion: "+CL_1_1+" available: "+platform.getVersion()); + return; + } + + CLContext context = CLContext.create(); + + final CLUserEvent customEvent = CLUserEvent.create(context); + + final CountDownLatch countdown = new CountDownLatch(1); + customEvent.registerCallback(new CLEventListener() { + + public void eventStateChanged(CLEvent event, int status) { + out.println("event received: "+event); + assertEquals(event, customEvent); + countdown.countDown(); + } + + }); + + customEvent.setStatus(ExecutionStatus.COMPLETE); + countdown.await(2, TimeUnit.SECONDS); + assertEquals(countdown.getCount(), 0); + + customEvent.release(); + + context.release(); + + } + + @Test public void concurrencyTest() throws IOException, InterruptedException { out.println(" - - - QueueBarrier test - - - "); |