}
extern "C" fn cl_enqueue_read_buffer(
- _command_queue: cl_command_queue,
- _buffer: cl_mem,
- _blocking_read: cl_bool,
- _offset: usize,
- _cb: usize,
- _ptr: *mut ::std::os::raw::c_void,
- _num_events_in_wait_list: cl_uint,
- _event_wait_list: *const cl_event,
- _event: *mut cl_event,
+ command_queue: cl_command_queue,
+ buffer: cl_mem,
+ blocking_read: cl_bool,
+ offset: usize,
+ cb: usize,
+ ptr: *mut ::std::os::raw::c_void,
+ num_events_in_wait_list: cl_uint,
+ event_wait_list: *const cl_event,
+ event: *mut cl_event,
) -> cl_int {
- println!("cl_enqueue_read_buffer not implemented");
- CL_OUT_OF_HOST_MEMORY
+ match_err!(enqueue_read_buffer(
+ command_queue,
+ buffer,
+ blocking_read,
+ offset,
+ cb,
+ ptr,
+ num_events_in_wait_list,
+ event_wait_list,
+ event
+ ))
}
extern "C" fn cl_enqueue_write_buffer(
Ok(cl_sampler::from_arc(sampler))
}
+pub fn enqueue_read_buffer(
+ command_queue: cl_command_queue,
+ buffer: cl_mem,
+ blocking_read: cl_bool,
+ offset: usize,
+ cb: usize,
+ ptr: *mut ::std::os::raw::c_void,
+ num_events_in_wait_list: cl_uint,
+ event_wait_list: *const cl_event,
+ event: *mut cl_event,
+) -> CLResult<()> {
+ let q = command_queue.get_arc()?;
+ let b = buffer.get_arc()?;
+ let block = check_cl_bool(blocking_read).ok_or(CL_INVALID_VALUE)?;
+ let evs = event_list_from_cl(&q, num_events_in_wait_list, event_wait_list)?;
+
+ // CL_INVALID_VALUE if the region being read or written specified by (offset, size) is out of
+ // bounds or if ptr is a NULL value.
+ if offset + cb > b.size || ptr.is_null() {
+ return Err(CL_INVALID_VALUE);
+ }
+
+ // CL_INVALID_CONTEXT if the context associated with command_queue and buffer are not the same
+ if b.context != q.context {
+ return Err(CL_INVALID_CONTEXT);
+ }
+
+ // CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST if the read and write operations are blocking
+ // and the execution status of any of the events in event_wait_list is a negative integer value.
+ if block && evs.iter().any(|e| e.is_error()) {
+ return Err(CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST);
+ }
+
+ // CL_INVALID_OPERATION if clEnqueueReadBuffer is called on buffer which has been created with
+ // CL_MEM_HOST_WRITE_ONLY or CL_MEM_HOST_NO_ACCESS.
+ if bit_check(b.flags, CL_MEM_HOST_WRITE_ONLY | CL_MEM_HOST_NO_ACCESS) {
+ return Err(CL_INVALID_OPERATION);
+ }
+
+ create_and_queue(
+ q,
+ CL_COMMAND_READ_BUFFER,
+ evs,
+ event,
+ block,
+ Box::new(move |q, ctx| b.read_to_user(q, ctx, offset, ptr, cb)),
+ )
+
+ // TODO
+ // CL_MISALIGNED_SUB_BUFFER_OFFSET if buffer is a sub-buffer object and offset specified when the sub-buffer object is created is not aligned to CL_DEVICE_MEM_BASE_ADDR_ALIGN value for device associated with queue.
+}
+
pub fn enqueue_write_buffer(
command_queue: cl_command_queue,
buffer: cl_mem,
.unwrap()
}
+ pub fn read_to_user(
+ &self,
+ q: &Arc<Queue>,
+ ctx: &Arc<PipeContext>,
+ offset: usize,
+ ptr: *mut c_void,
+ size: usize,
+ ) -> CLResult<()> {
+ // TODO support sub buffers
+ let r = self.get_res().get(&q.device).unwrap();
+ let tx = ctx.buffer_map(r, 0, self.size.try_into().unwrap(), true);
+
+ unsafe {
+ ptr::copy_nonoverlapping(tx.ptr().add(offset), ptr, size);
+ }
+
+ drop(tx);
+ Ok(())
+ }
+
pub fn write_from_user(
&self,
q: &Arc<Queue>,