rusticl: implement clEnqueueReadBuffer
authorKarol Herbst <kherbst@redhat.com>
Sat, 12 Mar 2022 19:02:04 +0000 (20:02 +0100)
committerMarge Bot <emma+marge@anholt.net>
Mon, 12 Sep 2022 05:58:12 +0000 (05:58 +0000)
Signed-off-by: Karol Herbst <kherbst@redhat.com>
Acked-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15439>

src/gallium/frontends/rusticl/api/icd.rs
src/gallium/frontends/rusticl/api/memory.rs
src/gallium/frontends/rusticl/core/memory.rs

index 051bc71..bbacf3a 100644 (file)
@@ -819,18 +819,27 @@ extern "C" fn cl_finish(command_queue: cl_command_queue) -> cl_int {
 }
 
 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(
index 6fade65..1f34260 100644 (file)
@@ -788,6 +788,58 @@ pub fn create_sampler(
     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,
index 56fd286..e884941 100644 (file)
@@ -195,6 +195,26 @@ impl 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>,