diff --git a/src/main/java/org/jocl/CL.java b/src/main/java/org/jocl/CL.java
index 8b6da12..a7ceb02 100644
--- a/src/main/java/org/jocl/CL.java
+++ b/src/main/java/org/jocl/CL.java
@@ -2000,22 +2000,35 @@ public static void setLogLevel(LogLevel logLevel)
-
/*
- * Implementation note concerning non-blocking writes:
+ * Implementation note concerning non-blocking operations:
+ * NON_BLOCKING_OPERATIONS
+ *
+ * Non-blocking operations are not supported for pointers to Java arrays.
+ * The Java array may be garbage collected if there no longer exists a
+ * reference to the array. But even if a reference is retained, the JVM
+ * memory management is allowed to move the memory of a Java array,
+ * at any time, unless the memory is "pinned" by calling
+ * GetPrimitiveArrayCritical. But this pinning cannot be done across
+ * multiple function calls.
+ */
+
+ /*
+ * Implementation note concerning non-blocking operations:
*
- * When a non-blocking write operation is scheduled, it might happen that
- * the source data (which is about to be written to an OpenCL memory
- * object) is garbage collected before the write operation is complete.
- * This could cause highly undeterministic errors, possibly crashes or
- * function calls that silently work on bogus data.
+ * When a non-blocking operation is scheduled, it might happen that
+ * the Java data (a direct buffer which is about to be filled from or
+ * written to an OpenCL memory object) is garbage collected before the
+ * operation is complete. This could cause highly undeterministic errors,
+ * possibly crashes or function calls that silently work on bogus data.
*
- * To avoid this, for each non-blocking write operation, a Runnable is
- * started (in an own thread), which only contains a reference to the
- * data and waits for the OpenCL event that is associated with the write
- * operation. Thus, it keeps the reference alive and prevents the data
- * from being garbage collected until the write operation is finished.
+ * To avoid this, for each non-blocking operation, a Runnable is started
+ * (in an own thread), which only contains a reference to the data and
+ * waits for the OpenCL event that is associated with the operation.
+ * Thus, it keeps the reference alive and prevents the data from being
+ * garbage collected until the operation is finished.
*/
+
/**
* Keep a reference to the given object, to prevent it from
* being garbage collected, until waiting for the given
@@ -6028,26 +6041,20 @@ public static int clSetCommandQueueProperty(cl_command_queue command_queue, long
*/
public static cl_mem clCreateBuffer(cl_context context, long flags, long size, Pointer host_ptr, int errcode_ret[])
{
- if (exceptionsEnabled)
+ if (exceptionsEnabled && errcode_ret == null)
{
- if (errcode_ret == null)
- {
- errcode_ret = new int[1];
- }
- cl_mem result = clCreateBufferNative(context, flags, size, host_ptr, errcode_ret);
- checkResult(errcode_ret[0]);
- return result;
+ errcode_ret = new int[1];
}
- else
+ cl_mem result = clCreateBufferNative(context, flags, size, host_ptr, errcode_ret);
+ if (exceptionsEnabled)
{
- cl_mem result = clCreateBufferNative(context, flags, size, host_ptr, errcode_ret);
- return result;
+ checkResult(errcode_ret[0]);
}
+ return result;
}
private static native cl_mem clCreateBufferNative(cl_context context, long flags, long size, Pointer host_ptr, int errcode_ret[]);
-
/**
* @deprecated The buffer_create_info that has to be passed to this function
* is specific for the underlying architecture (32/64 bit). The preferred
@@ -6810,25 +6817,27 @@ public static cl_mem clCreateSubBuffer(cl_mem buffer, /*cl_mem_flags*/ long flag
*
*
* @since OpenCL 1.2
+ * Note: If the given flags contain CL_MEM_USE_HOST_PTR
,
+ * then the given Pointer must be a Pointer to a direct buffer. Otherwise,
+ * an IllegalArgumentException will be thrown.
+ *
+ * @throws IllegalArgumentException If the given mapping flags contain
+ * CL_MEM_USE_HOST_PTR
, and the given Pointer is not
+ * a Pointer to a direct buffer.
*/
public static cl_mem clCreateImage(cl_context context, long flags, cl_image_format image_format, cl_image_desc image_desc, Pointer host_ptr, int errcode_ret[])
{
// OPENCL_1_2
- if (exceptionsEnabled)
+ if (exceptionsEnabled && errcode_ret == null)
{
- if (errcode_ret == null)
- {
- errcode_ret = new int[1];
- }
- cl_mem result = clCreateImageNative(context, flags, image_format, image_desc, host_ptr, errcode_ret);
- checkResult(errcode_ret[0]);
- return result;
+ errcode_ret = new int[1];
}
- else
+ cl_mem result = clCreateImageNative(context, flags, image_format, image_desc, host_ptr, errcode_ret);
+ if (exceptionsEnabled)
{
- cl_mem result = clCreateImageNative(context, flags, image_format, image_desc, host_ptr, errcode_ret);
- return result;
+ checkResult(errcode_ret[0]);
}
+ return result;
}
private static native cl_mem clCreateImageNative(cl_context context, long flags, cl_image_format image_format, cl_image_desc image_desc, Pointer host_ptr, int errcode_ret[]);
@@ -16339,48 +16348,43 @@ public static int clFinish(cl_command_queue command_queue)
*
*
*
- * Note: For non-blocking read operations, the given Pointer must be a
- * Pointer to a direct buffer. Otherwise, an IllegalArgumentException will
- * be thrown.
+ * Note: For non-blocking read operations, the given Pointer must be
+ * a Pointer to a direct buffer. Otherwise, an IllegalArgumentException
+ * will be thrown.
*
- * @throws IllegalArgumentException If blocking_read==false
and
- * the given Pointer is not a Pointer to a direct buffer.
+ * @throws IllegalArgumentException If blocking_read==false
+ * and the given Pointer is not a Pointer to a direct buffer.
*/
public static int clEnqueueReadBuffer(cl_command_queue command_queue, cl_mem buffer, boolean blocking_read, long offset, long cb, Pointer ptr, int num_events_in_wait_list, cl_event event_wait_list[], cl_event event)
{
-
- if (!blocking_read && !ptr.isDirectBufferPointer())
- {
- throw new IllegalArgumentException(
- "Non-blocking read operations may only be " +
- "performed using pointers to direct buffers");
- }
-
- return checkResult(clEnqueueReadBufferNative(command_queue, buffer, blocking_read, offset, cb, ptr, num_events_in_wait_list, event_wait_list, event));
-
- // NON_BLOCKING_READ
- /*
- //blocking_read = true;
-
if (blocking_read)
{
- int result = clEnqueueReadBufferNative(command_queue, buffer, blocking_read, offset, cb, ptr, num_events_in_wait_list, event_wait_list, event);
- return checkResult(result);
+ return checkResult(clEnqueueReadBufferNative(command_queue, buffer, blocking_read, offset, cb, ptr, num_events_in_wait_list, event_wait_list, event));
}
else
{
+ // See implementation notes about NON_BLOCKING_OPERATIONS
+ if (!blocking_read && !ptr.isDirectBufferPointer())
+ {
+ throw new IllegalArgumentException(
+ "Non-blocking read operations may only be " +
+ "performed using pointers to direct buffers");
+ }
+
boolean doRetainEvent = true;
if (event == null)
{
doRetainEvent = false;
event = new cl_event();
}
- int result = clEnqueueReadBufferNative(command_queue, buffer, blocking_read, offset, cb, ptr, num_events_in_wait_list, event_wait_list, event);
- clEnqueueMarker(command_queue, event);
- schedulePointerDataRelease(event);
+ int result = checkResult(clEnqueueReadBufferNative(command_queue, buffer, blocking_read, offset, cb, ptr, num_events_in_wait_list, event_wait_list, event));
+ // Only schedule the reference release if the enqueue succeeds.
+ if (result == CL_SUCCESS)
+ {
+ scheduleReferenceRelease(event, ptr, doRetainEvent);
+ }
return checkResult(result);
}
- */
}
private static native int clEnqueueReadBufferNative(cl_command_queue command_queue, cl_mem buffer, boolean blocking_read, long offset, long cb, Pointer ptr, int num_events_in_wait_list, cl_event event_wait_list[], cl_event event);
@@ -16650,17 +16654,45 @@ public static int clEnqueueReadBuffer(cl_command_queue command_queue, cl_mem buf
*
*
* @since OpenCL 1.1
+ *
+ * Note: For non-blocking read operations, the given Pointer must be
+ * a Pointer to a direct buffer. Otherwise, an IllegalArgumentException
+ * will be thrown.
+ *
+ * @throws IllegalArgumentException If blocking_read==false
+ * and the given Pointer is not a Pointer to a direct buffer.
*/
public static int clEnqueueReadBufferRect(cl_command_queue command_queue, cl_mem buffer, boolean blocking_read, long[] buffer_offset, long[] host_offset, long[] region, long buffer_row_pitch, long buffer_slice_pitch, long host_row_pitch, long host_slice_pitch, Pointer ptr, int num_events_in_wait_list, cl_event event_wait_list[], cl_event event)
{
// OPENCL_1_1
- if (!blocking_read && !ptr.isDirectBufferPointer())
+ if (blocking_read)
{
- throw new IllegalArgumentException(
- "Non-blocking read operations may only be " +
- "performed using pointers to direct buffers");
+ return checkResult(clEnqueueReadBufferRectNative(command_queue, buffer, blocking_read, buffer_offset, host_offset, region, buffer_row_pitch, buffer_slice_pitch, host_row_pitch, host_slice_pitch, ptr, num_events_in_wait_list, event_wait_list, event));
+ }
+ else
+ {
+ // See implementation notes about NON_BLOCKING_OPERATIONS
+ if (!blocking_read && !ptr.isDirectBufferPointer())
+ {
+ throw new IllegalArgumentException(
+ "Non-blocking read operations may only be " +
+ "performed using pointers to direct buffers");
+ }
+
+ boolean doRetainEvent = true;
+ if (event == null)
+ {
+ doRetainEvent = false;
+ event = new cl_event();
+ }
+ int result = checkResult(clEnqueueReadBufferRectNative(command_queue, buffer, blocking_read, buffer_offset, host_offset, region, buffer_row_pitch, buffer_slice_pitch, host_row_pitch, host_slice_pitch, ptr, num_events_in_wait_list, event_wait_list, event));
+ // Only schedule the reference release if the enqueue succeeds.
+ if (result == CL_SUCCESS)
+ {
+ scheduleReferenceRelease(event, ptr, doRetainEvent);
+ }
+ return checkResult(result);
}
- return checkResult(clEnqueueReadBufferRectNative(command_queue, buffer, blocking_read, buffer_offset, host_offset, region, buffer_row_pitch, buffer_slice_pitch, host_row_pitch, host_slice_pitch, ptr, num_events_in_wait_list, event_wait_list, event));
}
private static native int clEnqueueReadBufferRectNative(cl_command_queue command_queue, cl_mem buffer, boolean blocking_read, long[] buffer_offset, long[] host_offset, long[] region, long buffer_row_pitch, long buffer_slice_pitch, long host_row_pitch, long host_slice_pitch, Pointer ptr, int num_events_in_wait_list, cl_event event_wait_list[], cl_event event);
@@ -16912,6 +16944,13 @@ public static int clEnqueueReadBufferRect(cl_command_queue command_queue, cl_mem
*
*
*
+ *
+ * Note: For non-blocking write operations, the given Pointer must be
+ * a Pointer to a direct buffer. Otherwise, an IllegalArgumentException
+ * will be thrown.
+ *
+ * @throws IllegalArgumentException If blocking_write==false
+ * and the given Pointer is not a Pointer to a direct buffer.
*/
public static int clEnqueueWriteBuffer(cl_command_queue command_queue, cl_mem buffer, boolean blocking_write, long offset, long cb, Pointer ptr, int num_events_in_wait_list, cl_event event_wait_list[], cl_event event)
{
@@ -16921,6 +16960,14 @@ public static int clEnqueueWriteBuffer(cl_command_queue command_queue, cl_mem bu
}
else
{
+ // See implementation notes about NON_BLOCKING_WRITE
+ if (!blocking_write && !ptr.isDirectBufferPointer())
+ {
+ throw new IllegalArgumentException(
+ "Non-blocking write operations may only be " +
+ "performed using pointers to direct buffers");
+ }
+
boolean doRetainEvent = true;
if (event == null)
{
@@ -17219,7 +17266,34 @@ public static int clEnqueueWriteBuffer(cl_command_queue command_queue, cl_mem bu
public static int clEnqueueWriteBufferRect(cl_command_queue command_queue, cl_mem buffer, boolean blocking_write, long buffer_offset[], long host_offset[], long[] region, long buffer_row_pitch, long buffer_slice_pitch, long host_row_pitch, long host_slice_pitch, Pointer ptr, int num_events_in_wait_list, cl_event[] event_wait_list, cl_event event)
{
// OPENCL_1_1
- return checkResult(clEnqueueWriteBufferRectNative(command_queue, buffer, blocking_write, buffer_offset, host_offset, region, buffer_row_pitch, buffer_slice_pitch, host_row_pitch, host_slice_pitch, ptr, num_events_in_wait_list, event_wait_list, event));
+ if (blocking_write)
+ {
+ return checkResult(clEnqueueWriteBufferRectNative(command_queue, buffer, blocking_write, buffer_offset, host_offset, region, buffer_row_pitch, buffer_slice_pitch, host_row_pitch, host_slice_pitch, ptr, num_events_in_wait_list, event_wait_list, event));
+ }
+ else
+ {
+ // See implementation notes about NON_BLOCKING_WRITE
+ if (!blocking_write && !ptr.isDirectBufferPointer())
+ {
+ throw new IllegalArgumentException(
+ "Non-blocking write operations may only be " +
+ "performed using pointers to direct buffers");
+ }
+
+ boolean doRetainEvent = true;
+ if (event == null)
+ {
+ doRetainEvent = false;
+ event = new cl_event();
+ }
+ int result = checkResult(clEnqueueWriteBufferRectNative(command_queue, buffer, blocking_write, buffer_offset, host_offset, region, buffer_row_pitch, buffer_slice_pitch, host_row_pitch, host_slice_pitch, ptr, num_events_in_wait_list, event_wait_list, event));
+ // Only schedule the reference release if the enqueue succeeds.
+ if (result == CL_SUCCESS)
+ {
+ scheduleReferenceRelease(event, ptr, doRetainEvent);
+ }
+ return checkResult(result);
+ }
}
private static native int clEnqueueWriteBufferRectNative(cl_command_queue command_queue, cl_mem buffer, boolean blocking_write, long buffer_offset[], long host_offset[], long[] region, long buffer_row_pitch, long buffer_slice_pitch, long host_row_pitch, long host_slice_pitch, Pointer ptr, int num_events_in_wait_list, cl_event[] event_wait_list, cl_event event);
@@ -18224,18 +18298,43 @@ public static int clEnqueueCopyBufferRect(cl_command_queue command_queue, cl_mem
*
*
*
+ * Note: For non-blocking read operations, the given Pointer must be
+ * a Pointer to a direct buffer. Otherwise, an IllegalArgumentException
+ * will be thrown.
+ *
+ * @throws IllegalArgumentException If blocking_read==false
+ * and the given Pointer is not a Pointer to a direct buffer.
*/
public static int clEnqueueReadImage(cl_command_queue command_queue, cl_mem image, boolean blocking_read, long origin[], long region[], long row_pitch, long slice_pitch, Pointer ptr, int num_events_in_wait_list, cl_event event_wait_list[], cl_event event)
{
- if (!blocking_read && !ptr.isDirectBufferPointer())
+ if (blocking_read)
{
- throw new IllegalArgumentException(
- "Non-blocking read operations may only be " +
- "performed using pointers to direct buffers");
+ return checkResult(clEnqueueReadImageNative(command_queue, image, blocking_read, origin, region, row_pitch, slice_pitch, ptr, num_events_in_wait_list, event_wait_list, event));
}
- // NON_BLOCKING_READ (see clEnqueueReadBuffer)
+ else
+ {
+ // See implementation notes about NON_BLOCKING_OPERATIONS
+ if (!blocking_read && !ptr.isDirectBufferPointer())
+ {
+ throw new IllegalArgumentException(
+ "Non-blocking read operations may only be " +
+ "performed using pointers to direct buffers");
+ }
- return checkResult(clEnqueueReadImageNative(command_queue, image, blocking_read, origin, region, row_pitch, slice_pitch, ptr, num_events_in_wait_list, event_wait_list, event));
+ boolean doRetainEvent = true;
+ if (event == null)
+ {
+ doRetainEvent = false;
+ event = new cl_event();
+ }
+ int result = checkResult(clEnqueueReadImageNative(command_queue, image, blocking_read, origin, region, row_pitch, slice_pitch, ptr, num_events_in_wait_list, event_wait_list, event));
+ // Only schedule the reference release if the enqueue succeeds.
+ if (result == CL_SUCCESS)
+ {
+ scheduleReferenceRelease(event, ptr, doRetainEvent);
+ }
+ return checkResult(result);
+ }
}
private static native int clEnqueueReadImageNative(cl_command_queue command_queue, cl_mem image, boolean blocking_read, long origin[], long region[], long row_pitch, long slice_pitch, Pointer ptr, int num_events_in_wait_list, cl_event event_wait_list[], cl_event event);
@@ -18532,6 +18631,14 @@ public static int clEnqueueWriteImage(cl_command_queue command_queue, cl_mem ima
}
else
{
+ // See implementation notes about NON_BLOCKING_WRITE
+ if (!blocking_write && !ptr.isDirectBufferPointer())
+ {
+ throw new IllegalArgumentException(
+ "Non-blocking write operations may only be " +
+ "performed using pointers to direct buffers");
+ }
+
boolean doRetainEvent = true;
if (event == null)
{
@@ -19715,21 +19822,16 @@ public static int clEnqueueCopyBufferToImage(cl_command_queue command_queue, cl_
*/
public static ByteBuffer clEnqueueMapBuffer(cl_command_queue command_queue, cl_mem buffer, boolean blocking_map, long map_flags, long offset, long cb, int num_events_in_wait_list, cl_event event_wait_list[], cl_event event, int errcode_ret[])
{
- if (exceptionsEnabled)
+ if (exceptionsEnabled && errcode_ret == null)
{
- if (errcode_ret == null)
- {
- errcode_ret = new int[1];
- }
- ByteBuffer result = clEnqueueMapBufferNative(command_queue, buffer, blocking_map, map_flags, offset, cb, num_events_in_wait_list, event_wait_list, event, errcode_ret);
- checkResult(errcode_ret[0]);
- return result;
+ errcode_ret = new int[1];
}
- else
+ ByteBuffer result = clEnqueueMapBufferNative(command_queue, buffer, blocking_map, map_flags, offset, cb, num_events_in_wait_list, event_wait_list, event, errcode_ret);
+ if (exceptionsEnabled)
{
- ByteBuffer result = clEnqueueMapBufferNative(command_queue, buffer, blocking_map, map_flags, offset, cb, num_events_in_wait_list, event_wait_list, event, errcode_ret);
- return result;
+ checkResult(errcode_ret[0]);
}
+ return result;
}
private static native ByteBuffer clEnqueueMapBufferNative(cl_command_queue command_queue, cl_mem buffer, boolean blocking_map, long map_flags, long offset, long cb, int num_events_in_wait_list, cl_event event_wait_list[], cl_event event, int errcode_ret[]);
@@ -20045,21 +20147,16 @@ public static ByteBuffer clEnqueueMapBuffer(cl_command_queue command_queue, cl_m
*/
public static ByteBuffer clEnqueueMapImage(cl_command_queue command_queue, cl_mem image, boolean blocking_map, long map_flags, long origin[], long region[], long image_row_pitch[], long image_slice_pitch[], int num_events_in_wait_list, cl_event event_wait_list[], cl_event event, int errcode_ret[])
{
- if (exceptionsEnabled)
+ if (exceptionsEnabled && errcode_ret == null)
{
- if (errcode_ret == null)
- {
- errcode_ret = new int[1];
- }
- ByteBuffer result = clEnqueueMapImageNative(command_queue, image, blocking_map, map_flags, origin, region, image_row_pitch, image_slice_pitch, num_events_in_wait_list, event_wait_list, event, errcode_ret);
- checkResult(errcode_ret[0]);
- return result;
+ errcode_ret = new int[1];
}
- else
+ ByteBuffer result = clEnqueueMapImageNative(command_queue, image, blocking_map, map_flags, origin, region, image_row_pitch, image_slice_pitch, num_events_in_wait_list, event_wait_list, event, errcode_ret);
+ if (exceptionsEnabled)
{
- ByteBuffer result = clEnqueueMapImageNative(command_queue, image, blocking_map, map_flags, origin, region, image_row_pitch, image_slice_pitch, num_events_in_wait_list, event_wait_list, event, errcode_ret);
- return result;
+ checkResult(errcode_ret[0]);
}
+ return result;
}
private static native ByteBuffer clEnqueueMapImageNative(cl_command_queue command_queue, cl_mem image, boolean blocking_map, long map_flags, long origin[], long region[], long image_row_pitch[], long image_slice_pitch[], int num_events_in_wait_list, cl_event event_wait_list[], cl_event event, int errcode_ret[]);
@@ -25829,39 +25926,41 @@ public static synchronized ByteBuffer allocateAligned(int size, int alignment)
/**
- * This method may be used to manually free an aligned ByteBuffer which
+ * This method will free the memory of an aligned ByteBuffer which
* was allocated with {@link CL#allocateAligned(int, int)}.
*
- * @param byteBuffer The byte buffer
+ * @param pointer The pointer whose nativePointer value is the address
+ * of the native, aligned byte buffer that was set in the native
+ * implementation of {@link CL#allocateAligned(int, int)}
*/
- // This is not required, and might be error-prone because of
- // making the given Buffer invalid.
- /*
- private static synchronized void freeAligned(ByteBuffer byteBuffer)
+ private static native void freeAlignedNative(Pointer pointer);
+
+
+ // Method to validate a combination of flags and a given pointer.
+ // This is not used until now, but might become necessary in view
+ // of https://github.com/gpu/JOCL/issues/7
+ private static void validateHostPointerFlags(long flags, Pointer pointer)
{
- if (byteBuffer == null)
+ if ((flags & CL_MEM_USE_HOST_PTR) == 0)
{
return;
}
- for (Map.Entry, Pointer> entry : alignedByteBufferMap.entrySet())
+ if (pointer == null)
{
- WeakReference reference = entry.getKey();
- if (reference.get() == byteBuffer)
- {
- Pointer pointer = entry.getValue();
- if (pointer != null)
- {
- freeAlignedNative(pointer);
- }
- alignedByteBufferMap.remove(reference);
- return;
- }
+ // This will cause an OpenCL error later
+ return;
+ }
+ if ((flags & CL_MEM_WRITE_ONLY) != 0)
+ {
+ return;
+ }
+ if (!pointer.isDirectBufferPointer())
+ {
+ throw new IllegalArgumentException(
+ "The CL_MEM_USE_HOST_PTR flag may only be used with " +
+ "read-only pointers to Java arrays, or with pointers " +
+ "to direct buffers");
}
}
- */
- private static native void freeAlignedNative(Pointer pointer);
-
-
-
-
+
}
diff --git a/src/test/java/org/jocl/test/TestNonBlockingConstraints.java b/src/test/java/org/jocl/test/TestNonBlockingConstraints.java
new file mode 100644
index 0000000..ab5b1a8
--- /dev/null
+++ b/src/test/java/org/jocl/test/TestNonBlockingConstraints.java
@@ -0,0 +1,143 @@
+package org.jocl.test;
+
+import static org.jocl.CL.CL_MEM_READ_ONLY;
+import static org.jocl.CL.CL_MEM_WRITE_ONLY;
+import static org.jocl.CL.CL_NON_BLOCKING;
+import static org.jocl.CL.clCreateBuffer;
+import static org.jocl.CL.clEnqueueReadBuffer;
+import static org.jocl.CL.clEnqueueWriteBuffer;
+import static org.jocl.CL.clFinish;
+import static org.jocl.CL.clFlush;
+
+import java.nio.ByteBuffer;
+
+import org.jocl.Pointer;
+import org.jocl.Sizeof;
+import org.jocl.cl_mem;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+/**
+ * Test the constraints for non-blocking operations, and whether the
+ * IllegalArgumentException is thrown accordingly:
+ * A non-blocking operation will
+ * - throw for a pointer to a Java array
+ * - throw for a pointer to a Java byte buffer
+ * - NOT throw for a pointer to a DIRECT byte buffer
+ */
+public class TestNonBlockingConstraints extends JOCLAbstractTest
+{
+ @Rule
+ public final ExpectedException exception = ExpectedException.none();
+
+ @Test
+ public void testNonBlockingReadWithJavaArrayThrows()
+ {
+ initCL(defaultPlatformIndex, defaultDeviceType, defaultDeviceIndex);
+
+ cl_mem mem = clCreateBuffer(context, CL_MEM_READ_ONLY,
+ 10 * Sizeof.cl_float, null, null);
+
+ Pointer pointer = Pointer.to(new float[10]);
+
+ exception.expect(IllegalArgumentException.class);
+ clEnqueueReadBuffer(commandQueue, mem, CL_NON_BLOCKING, 0,
+ 10 * Sizeof.cl_float, pointer, 0, null, null);
+
+ clFlush(commandQueue);
+ clFinish(commandQueue);
+ }
+
+ @Test
+ public void testNonBlockingReadWithBufferThrows()
+ {
+ initCL(defaultPlatformIndex, defaultDeviceType, defaultDeviceIndex);
+
+ cl_mem mem = clCreateBuffer(context, CL_MEM_READ_ONLY,
+ 10 * Sizeof.cl_float, null, null);
+
+ Pointer pointer = Pointer.to(ByteBuffer.allocate(10 * Sizeof.cl_float));
+
+ exception.expect(IllegalArgumentException.class);
+ clEnqueueReadBuffer(commandQueue, mem, CL_NON_BLOCKING, 0,
+ 10 * Sizeof.cl_float, pointer, 0, null, null);
+
+ clFlush(commandQueue);
+ clFinish(commandQueue);
+ }
+
+ @Test
+ public void testNonBlockingReadWithDirectBuffer()
+ {
+ initCL(defaultPlatformIndex, defaultDeviceType, defaultDeviceIndex);
+
+ cl_mem mem = clCreateBuffer(context, CL_MEM_READ_ONLY,
+ 10 * Sizeof.cl_float, null, null);
+
+ Pointer pointer = Pointer.to(
+ ByteBuffer.allocateDirect(10 * Sizeof.cl_float));
+
+ clEnqueueReadBuffer(commandQueue, mem, CL_NON_BLOCKING, 0,
+ 10 * Sizeof.cl_float, pointer, 0, null, null);
+
+ clFlush(commandQueue);
+ clFinish(commandQueue);
+ }
+
+
+ @Test
+ public void testNonBlockingWriteWithJavaArrayThrows()
+ {
+ initCL(defaultPlatformIndex, defaultDeviceType, defaultDeviceIndex);
+
+ cl_mem mem = clCreateBuffer(context, CL_MEM_WRITE_ONLY,
+ 10 * Sizeof.cl_float, null, null);
+
+ Pointer pointer = Pointer.to(new float[10]);
+
+ exception.expect(IllegalArgumentException.class);
+ clEnqueueWriteBuffer(commandQueue, mem, CL_NON_BLOCKING, 0,
+ 10 * Sizeof.cl_float, pointer, 0, null, null);
+
+ clFlush(commandQueue);
+ clFinish(commandQueue);
+ }
+
+ @Test
+ public void testNonBlockingWriteWithBufferThrows()
+ {
+ initCL(defaultPlatformIndex, defaultDeviceType, defaultDeviceIndex);
+
+ cl_mem mem = clCreateBuffer(context, CL_MEM_WRITE_ONLY,
+ 10 * Sizeof.cl_float, null, null);
+
+ Pointer pointer = Pointer.to(ByteBuffer.allocate(10 * Sizeof.cl_float));
+
+ exception.expect(IllegalArgumentException.class);
+ clEnqueueWriteBuffer(commandQueue, mem, CL_NON_BLOCKING, 0,
+ 10 * Sizeof.cl_float, pointer, 0, null, null);
+
+ clFlush(commandQueue);
+ clFinish(commandQueue);
+ }
+
+ @Test
+ public void testNonBlockingWriteWithDirectBuffer()
+ {
+ initCL(defaultPlatformIndex, defaultDeviceType, defaultDeviceIndex);
+
+ cl_mem mem = clCreateBuffer(context, CL_MEM_READ_ONLY,
+ 10 * Sizeof.cl_float, null, null);
+
+ Pointer pointer = Pointer.to(
+ ByteBuffer.allocateDirect(10 * Sizeof.cl_float));
+
+ clEnqueueWriteBuffer(commandQueue, mem, CL_NON_BLOCKING, 0,
+ 10 * Sizeof.cl_float, pointer, 0, null, null);
+
+ clFlush(commandQueue);
+ clFinish(commandQueue);
+ }
+
+}