diff options
author | Michael Bien <[email protected]> | 2010-05-04 02:22:19 +0200 |
---|---|---|
committer | Michael Bien <[email protected]> | 2010-05-04 02:22:19 +0200 |
commit | 9125a275449cb533798357914945de1f742a91f9 (patch) | |
tree | c25d5357ac99ec24bee4e7f2c95775362877db0b | |
parent | ea95ca1b96300fc9b2ec937759663eb0ed1406bf (diff) |
finished main functionality of ErrorHandler impl.
- using event listener add/remove pattern instead add on context creation
- context -> error handler object global reference mapping(TM) using LongLongMap in CLImpl
- global ref is deleted on context release
-rw-r--r-- | resources/cl-if.cfg | 4 | ||||
-rw-r--r-- | resources/cl-impl.cfg | 1 | ||||
-rw-r--r-- | resources/clImplCustomCode.c | 66 | ||||
-rw-r--r-- | resources/clImplCustomCode.java | 49 | ||||
-rw-r--r-- | src/com/jogamp/opencl/CLContext.java | 92 | ||||
-rw-r--r-- | src/com/jogamp/opencl/CLErrorHandler.java | 5 | ||||
-rw-r--r-- | src/com/jogamp/opencl/gl/CLGLContext.java | 14 |
7 files changed, 187 insertions, 44 deletions
diff --git a/resources/cl-if.cfg b/resources/cl-if.cfg index d0413d97..6f19e64f 100644 --- a/resources/cl-if.cfg +++ b/resources/cl-if.cfg @@ -21,12 +21,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(PointerBuffer properties, PointerBuffer devices, CreateContextCallback pfn_notify, IntBuffer errcode_ret); +CustomJavaCode CL public long clCreateContext(PointerBuffer properties, PointerBuffer devices, CLErrorHandler pfn_notify, 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(PointerBuffer properties, long device_type, CreateContextCallback pfn_notify, IntBuffer errcode_ret); +CustomJavaCode CL public long clCreateContextFromType(PointerBuffer properties, long device_type, CLErrorHandler pfn_notify, IntBuffer errcode_ret); Ignore clBuildProgram CustomJavaCode CL diff --git a/resources/cl-impl.cfg b/resources/cl-impl.cfg index 34753eb7..fc04d2b0 100644 --- a/resources/cl-impl.cfg +++ b/resources/cl-impl.cfg @@ -46,6 +46,7 @@ Ignore clCreateContext Ignore clCreateContextFromType Ignore clBuildProgram Ignore clEnqueueNativeKernel +Ignore clReleaseContext #take buffer capacity from input param 5 ReturnValueCapacity clEnqueueMapBuffer {5} diff --git a/resources/clImplCustomCode.c b/resources/clImplCustomCode.c index b491eb7f..1314e7b8 100644 --- a/resources/clImplCustomCode.c +++ b/resources/clImplCustomCode.c @@ -25,7 +25,7 @@ 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/CreateContextCallback"); + jclass errorHandlerClassID = (*env)->FindClass(env, "com/jogamp/opencl/CLErrorHandler"); // throws even more reflection Exceptions // IDs are unique and do not change @@ -35,7 +35,7 @@ JNI_OnLoad(JavaVM * _jvm, void *reserved) { if (errorHandlerClassID != NULL) { cccb_mid = (*env)->GetMethodID(env, errorHandlerClassID, "onError", "(Ljava/lang/String;Ljava/nio/ByteBuffer;J)V"); } - + return JNI_VERSION_1_2; } @@ -47,8 +47,10 @@ void buildProgramCallback(cl_program id, void * object) { (*jvm)->AttachCurrentThread(jvm, (void **)&env, NULL); - (*env)->CallVoidMethod(env, obj, bcb_mid, (jlong)id); - (*env)->DeleteGlobalRef(env, obj); + (*env)->CallVoidMethod(env, obj, bcb_mid, (jlong)id); + (*env)->DeleteGlobalRef(env, obj); + + (*jvm)->DetachCurrentThread(jvm); } @@ -59,11 +61,12 @@ void createContextCallback(const char * errinfo, const void * private_info, size (*jvm)->AttachCurrentThread(jvm, (void **)&env, NULL); - jstring errorString = (*env)->NewStringUTF(env, errinfo); + jstring errorString = (*env)->NewStringUTF(env, errinfo); - //TODO private_info - (*env)->CallVoidMethod(env, obj, cccb_mid, errorString, NULL, 0); - //(*env)->DeleteGlobalRef(env, obj); + //TODO private_info + (*env)->CallVoidMethod(env, obj, cccb_mid, errorString, NULL, 0); + + (*jvm)->DetachCurrentThread(jvm); } @@ -80,7 +83,7 @@ void createContextCallback(const char * errinfo, const void * private_info, size */ JNIEXPORT jlong JNICALL Java_com_jogamp_opencl_impl_CLImpl_clCreateContextFromType0(JNIEnv *env, jobject _unused, - jobject props, jint props_byte_offset, jobject device_type, jobject cb, jobject errcode, jint errcode_byte_offset) { + jobject props, jint props_byte_offset, jobject device_type, jobject cb, jobject global, jobject errcode, jint errcode_byte_offset) { cl_context_properties* _props_ptr = NULL; int32_t * _errcode_ptr = NULL; @@ -103,9 +106,16 @@ Java_com_jogamp_opencl_impl_CLImpl_clCreateContextFromType0(JNIEnv *env, jobject _ctx = clCreateContextFromType(_props_ptr, (uint64_t) device_type, pfn_notify, globalCB, (int32_t *) _errcode_ptr); - // if something went wrong - if (_ctx == NULL && globalCB != NULL) { - (*env)->DeleteGlobalRef(env, globalCB); + if(globalCB != NULL) { + jlong *g = (*env)->GetPrimitiveArrayCritical(env, global, NULL); + // if something went wrong + if(_ctx == NULL) { + g[0] = 0; + (*env)->DeleteGlobalRef(env, globalCB); + }else{ + g[0] = (jlong)globalCB; + } + (*env)->ReleasePrimitiveArrayCritical(env, global, g, 0); } return (jlong) (intptr_t)_ctx; @@ -123,7 +133,7 @@ Java_com_jogamp_opencl_impl_CLImpl_clCreateContextFromType0(JNIEnv *env, jobject */ JNIEXPORT jlong JNICALL Java_com_jogamp_opencl_impl_CLImpl_clCreateContext0(JNIEnv *env, jobject _unused, - jobject props, jint props_byte_offset, jint numDevices, jobject deviceList, jint device_type_offset, jobject cb, jobject errcode, jint errcode_byte_offset) { + jobject props, jint props_byte_offset, jint numDevices, jobject deviceList, jint device_type_offset, jobject cb, jobject global, jobject errcode, jint errcode_byte_offset) { cl_context_properties* _props_ptr = NULL; int32_t * _errcode_ptr = NULL; @@ -149,14 +159,38 @@ Java_com_jogamp_opencl_impl_CLImpl_clCreateContext0(JNIEnv *env, jobject _unused _ctx = clCreateContext(_props_ptr, numDevices, (cl_device_id *)_deviceListPtr, pfn_notify, globalCB, (int32_t *) _errcode_ptr); - // if something went wrong - if (_ctx == NULL && globalCB != NULL) { - (*env)->DeleteGlobalRef(env, globalCB); + if(globalCB != NULL) { + jlong *g = (*env)->GetPrimitiveArrayCritical(env, global, NULL); + // if something went wrong + if(_ctx == NULL) { + g[0] = 0; + (*env)->DeleteGlobalRef(env, globalCB); + }else{ + g[0] = (jlong)globalCB; + } + (*env)->ReleasePrimitiveArrayCritical(env, global, g, 0); } return (jlong) (intptr_t)_ctx; } +/* Java->C glue code: + * Java package: com.jogamp.opencl.impl.CLImpl + * Java method: int clReleaseContextImpl(long context) + * C function: int32_t clReleaseContextImpl(cl_context context); + */ +JNIEXPORT jint JNICALL +Java_com_jogamp_opencl_impl_CLImpl_clReleaseContextImpl(JNIEnv *env, jobject _unused, jlong context, jlong global) { + int32_t _res; + _res = clReleaseContext((cl_context) (intptr_t) context); + // TODO deal with retains + if (global != 0) { + (*env)->DeleteGlobalRef(env, (jobject) global); + } + return _res; +} + + /** * Entry point to C language function: * extern CL_API_ENTRY cl_int CL_API_CALL diff --git a/resources/clImplCustomCode.java b/resources/clImplCustomCode.java index f3daddf0..d2993f96 100644 --- a/resources/clImplCustomCode.java +++ b/resources/clImplCustomCode.java @@ -1,33 +1,66 @@ private final CLProcAddressTable addressTable; + //maps the context id to its error handler's global object pointer + private final com.jogamp.common.util.LongLongHashMap contextCallbackMap; + public CLImpl(CLProcAddressTable addressTable) { this.addressTable = addressTable; + this.contextCallbackMap = new com.jogamp.common.util.LongLongHashMap(); + this.contextCallbackMap.setKeyNotFoundValue(0); } - public long clCreateContext(PointerBuffer properties, PointerBuffer devices, CreateContextCallback pfn_notify, IntBuffer errcode_ret) { + public long clCreateContext(PointerBuffer properties, PointerBuffer devices, CLErrorHandler pfn_notify, IntBuffer errcode_ret) { if(properties!=null && !properties.isDirect()) throw new RuntimeException("Argument \"properties\" was not a direct buffer"); - return this.clCreateContext0( + long[] global = new long[1]; + long ctx = this.clCreateContext0( properties!=null?properties.getBuffer():null, Buffers.getDirectBufferByteOffset(properties), devices!=null?devices.remaining():0, devices!=null?devices.getBuffer():null, Buffers.getDirectBufferByteOffset(devices), - null, errcode_ret, Buffers.getDirectBufferByteOffset(errcode_ret) ); + pfn_notify, global, errcode_ret, Buffers.getDirectBufferByteOffset(errcode_ret) ); + + if(pfn_notify != null && global[0] != 0) { + synchronized(contextCallbackMap) { + contextCallbackMap.put(ctx, global[0]); + } + } + return ctx; } - private native long clCreateContext0(Object cl_context_properties, int props_offset, int numDevices, Object devices, int devices_offset, CreateContextCallback pfn_notify, Object errcode_ret, int err_offset); + private native long clCreateContext0(Object cl_context_properties, int props_offset, int numDevices, Object devices, int devices_offset, CLErrorHandler pfn_notify, long[] global, Object errcode_ret, int err_offset); - public long clCreateContextFromType(PointerBuffer properties, long device_type, CreateContextCallback pfn_notify, IntBuffer errcode_ret) { + public long clCreateContextFromType(PointerBuffer properties, long device_type, CLErrorHandler pfn_notify, IntBuffer errcode_ret) { if(properties!=null && !properties.isDirect()) throw new RuntimeException("Argument \"properties\" was not a direct buffer"); - return this.clCreateContextFromType0( + long[] global = new long[1]; + long ctx = this.clCreateContextFromType0( properties!=null?properties.getBuffer():null, Buffers.getDirectBufferByteOffset(properties), - device_type, pfn_notify, errcode_ret, Buffers.getDirectBufferByteOffset(errcode_ret) ); + device_type, pfn_notify, global, errcode_ret, Buffers.getDirectBufferByteOffset(errcode_ret) ); + + if(pfn_notify != null && global[0] != 0) { + synchronized(contextCallbackMap) { + contextCallbackMap.put(ctx, global[0]); + } + } + return ctx; } - private native long clCreateContextFromType0(Object properties, int props_offset, long device_type, CreateContextCallback pfn_notify, Object errcode_ret, int err_offset); + private native long clCreateContextFromType0(Object properties, int props_offset, long device_type, CLErrorHandler pfn_notify, long[] global, Object errcode_ret, int err_offset); + + + public int clReleaseContext(long context) { + long global = 0; + synchronized(contextCallbackMap) { + global = contextCallbackMap.remove(context); + } + return clReleaseContextImpl(context, global); + } + + /** Interface to C language function: <br> <code> int32_t {@native clReleaseContext}(cl_context context); </code> */ + public native int clReleaseContextImpl(long context, long global); /** Interface to C language function: <br> <code> int32_t clBuildProgram(cl_program, uint32_t, cl_device_id * , const char * , void * ); </code> */ diff --git a/src/com/jogamp/opencl/CLContext.java b/src/com/jogamp/opencl/CLContext.java index e9e0a8a8..c904a37c 100644 --- a/src/com/jogamp/opencl/CLContext.java +++ b/src/com/jogamp/opencl/CLContext.java @@ -24,6 +24,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import static java.lang.System.*; import static com.jogamp.opencl.CLException.*; import static com.jogamp.common.nio.Buffers.*; import static com.jogamp.common.os.Platform.*; @@ -45,15 +46,26 @@ public class CLContext extends CLObject implements CLResource { protected final Map<CLDevice, List<CLCommandQueue>> queuesMap; protected final CLPlatform platform; + + private final ErrorDispatcher errorHandler; - - protected CLContext(CLPlatform platform, long contextID) { + protected CLContext(CLPlatform platform, long contextID, ErrorDispatcher dispatcher) { super(CLPlatform.getLowLevelCLInterface(), contextID); this.platform = platform; this.programs = new ArrayList<CLProgram>(); this.samplers = new ArrayList<CLSampler>(); this.memoryObjects = new ArrayList<CLMemory<? extends Buffer>>(); this.queuesMap = new HashMap<CLDevice, List<CLCommandQueue>>(); + this.errorHandler = dispatcher; + + /* + addCLErrorHandler(new CLErrorHandler() { + public void onError(String errinfo, ByteBuffer private_info, long cb) { + java.util.logging.Logger.getLogger(getClass().getName()).warning(errinfo); + } + }); + */ + } private void initDevices() { @@ -88,7 +100,7 @@ public class CLContext extends CLObject implements CLResource { * Creates a context on the specified device types. * The platform to be used is implementation dependent. */ - public static CLContext create(CLDevice.Type... deviceTypes) { + public static CLContext create(Type... deviceTypes) { return create(null, deviceTypes); } @@ -104,14 +116,14 @@ public class CLContext extends CLObject implements CLResource { * Creates a context on the specified platform on all available devices (CL_DEVICE_TYPE_ALL). */ public static CLContext create(CLPlatform platform) { - return create(platform, CLDevice.Type.ALL); + return create(platform, Type.ALL); } /** * Creates a context on the specified platform and with the specified * device types. */ - public static CLContext create(CLPlatform platform, CLDevice.Type... deviceTypes) { + public static CLContext create(CLPlatform platform, Type... deviceTypes) { if(platform == null) { platform = CLPlatform.getDefault(); @@ -120,7 +132,8 @@ public class CLContext extends CLObject implements CLResource { long type = toDeviceBitmap(deviceTypes); PointerBuffer properties = setupContextProperties(platform); - return new CLContext(platform, createContextFromType(properties, type)); + ErrorDispatcher dispatcher = new ErrorDispatcher(); + return new CLContext(platform, createContextFromType(dispatcher, properties, type), dispatcher); } /** @@ -134,7 +147,8 @@ public class CLContext extends CLObject implements CLResource { } PointerBuffer properties = setupContextProperties(platform); - CLContext context = new CLContext(platform, createContext(properties, devices)); + ErrorDispatcher dispatcher = new ErrorDispatcher(); + CLContext context = new CLContext(platform, createContext(dispatcher, properties, devices), dispatcher); if(devices != null) { for (int i = 0; i < devices.length; i++) { devices[i].setContext(context); @@ -143,17 +157,17 @@ public class CLContext extends CLObject implements CLResource { return context; } - protected static long createContextFromType(PointerBuffer properties, long deviceType) { + protected static long createContextFromType(CLErrorHandler handler, PointerBuffer properties, long deviceType) { IntBuffer status = IntBuffer.allocate(1); - long context = CLPlatform.getLowLevelCLInterface().clCreateContextFromType(properties, deviceType, null, status); + long context = CLPlatform.getLowLevelCLInterface().clCreateContextFromType(properties, deviceType, handler, status); checkForError(status.get(), "can not create CL context"); return context; } - protected static long createContext(PointerBuffer properties, CLDevice... devices) { + protected static long createContext(CLErrorHandler handler, PointerBuffer properties, CLDevice... devices) { IntBuffer status = newDirectIntBuffer(1); PointerBuffer pb = null; @@ -167,7 +181,7 @@ public class CLContext extends CLObject implements CLResource { pb.put(i, device.ID); } } - long context = CLPlatform.getLowLevelCLInterface().clCreateContext(properties, pb, null, status); + long context = CLPlatform.getLowLevelCLInterface().clCreateContext(properties, pb, handler, status); checkForError(status.get(), "can not create CL context"); @@ -353,6 +367,14 @@ public class CLContext extends CLObject implements CLResource { samplers.remove(sampler); } + public void addCLErrorHandler(CLErrorHandler handler) { + errorHandler.addHandler(handler); + } + + public void removeCLErrorHandler(CLErrorHandler handler) { + errorHandler.removeHandler(handler); + } + /** * Releases the context and all resources. */ @@ -513,4 +535,52 @@ public class CLContext extends CLObject implements CLResource { return hash; } + protected static ErrorDispatcher createErrorHandler() { + return new ErrorDispatcher(); + } + + protected static class ErrorDispatcher implements CLErrorHandler { + + private volatile CLErrorHandler[] clientHandlers = new CLErrorHandler[0]; + + public void onError(String errinfo, ByteBuffer private_info, long cb) { + CLErrorHandler[] handlers = this.clientHandlers; + for (int i = 0; i < handlers.length; i++) { + handlers[i].onError(errinfo, private_info, cb); + } + } + + private void addHandler(CLErrorHandler handler) { + + if(handler == null) { + throw new IllegalArgumentException("handler was null."); + } + + CLErrorHandler[] handlers = new CLErrorHandler[clientHandlers.length+1]; + arraycopy(clientHandlers, 0, handlers, 0, clientHandlers.length); + handlers[handlers.length-1] = handler; + clientHandlers = handlers; + } + + private void removeHandler(CLErrorHandler handler) { + + if(handler == null) { + throw new IllegalArgumentException("handler was null."); + } + + for (int i = 0; i < clientHandlers.length; i++) { + if(handler.equals(clientHandlers[i])) { + CLErrorHandler[] handlers = new CLErrorHandler[clientHandlers.length-1]; + arraycopy(clientHandlers, 0, handlers, 0, i); + arraycopy(clientHandlers, i, handlers, 0, handlers.length-i); + clientHandlers = handlers; + return; + } + } + } + + + } + + } diff --git a/src/com/jogamp/opencl/CLErrorHandler.java b/src/com/jogamp/opencl/CLErrorHandler.java index 74d49363..6a1cfb89 100644 --- a/src/com/jogamp/opencl/CLErrorHandler.java +++ b/src/com/jogamp/opencl/CLErrorHandler.java @@ -3,8 +3,11 @@ package com.jogamp.opencl; import java.nio.ByteBuffer; /** - * + * Experimental: the api may change in future, feedback appreciated.<br/> + * Note: the thread which calls {@link #onError onError} is unspecified. The Application must ensure propper synchronization. * @author Michael Bien + * @see CLContext#addCLErrorHandler(com.jogamp.opencl.CLErrorHandler) + * @see CLContext#removeCLErrorHandler(com.jogamp.opencl.CLErrorHandler) */ public interface CLErrorHandler { diff --git a/src/com/jogamp/opencl/gl/CLGLContext.java b/src/com/jogamp/opencl/gl/CLGLContext.java index 7b574664..dde05e75 100644 --- a/src/com/jogamp/opencl/gl/CLGLContext.java +++ b/src/com/jogamp/opencl/gl/CLGLContext.java @@ -23,8 +23,8 @@ public final class CLGLContext extends CLContext { final long glID; private final GLContext glContext; - private CLGLContext(CLPlatform platform, GLContext glContext, long clContextID, long glContextID) { - super(platform, clContextID); + private CLGLContext(CLPlatform platform, GLContext glContext, long clContextID, long glContextID, ErrorDispatcher dispatcher) { + super(platform, clContextID, dispatcher); this.glID = glContextID; this.glContext = glContext; } @@ -81,9 +81,10 @@ public final class CLGLContext extends CLContext { long[] glID = new long[1]; PointerBuffer properties = setupContextProperties(platform, glContext, glID); - long clID = createContextFromType(properties, toDeviceBitmap(deviceTypes)); + ErrorDispatcher dispatcher = createErrorHandler(); + long clID = createContextFromType(dispatcher, properties, toDeviceBitmap(deviceTypes)); - return new CLGLContext(platform, glContext, clID, glID[0]); + return new CLGLContext(platform, glContext, clID, glID[0], dispatcher); } @@ -101,9 +102,10 @@ public final class CLGLContext extends CLContext { long[] glID = new long[1]; PointerBuffer properties = setupContextProperties(platform, glContext, glID); - long clID = createContext(properties, devices); + ErrorDispatcher dispatcher = createErrorHandler(); + long clID = createContext(dispatcher, properties, devices); - CLGLContext context = new CLGLContext(platform, glContext, clID, glID[0]); + CLGLContext context = new CLGLContext(platform, glContext, clID, glID[0], dispatcher); if(devices != null) { for (int i = 0; i < devices.length; i++) { context.overrideContext(devices[i]); |