rusticl/mem: implement copy image
authorKarol Herbst <kherbst@redhat.com>
Thu, 24 Mar 2022 17:21:44 +0000 (18:21 +0100)
committerMarge Bot <emma+marge@anholt.net>
Mon, 12 Sep 2022 05:58:13 +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/memory.rs
src/gallium/frontends/rusticl/api/types.rs
src/gallium/frontends/rusticl/core/memory.rs
src/gallium/frontends/rusticl/mesa/pipe/context.rs

index 9609da9..1f0e6f0 100644 (file)
@@ -983,7 +983,16 @@ pub fn enqueue_copy_buffer(
         evs,
         event,
         false,
-        Box::new(move |q, ctx| src.copy_to(q, ctx, &dst, src_offset, dst_offset, size)),
+        Box::new(move |q, ctx| {
+            src.copy_to(
+                q,
+                ctx,
+                &dst,
+                CLVec::new([src_offset, 0, 0]),
+                CLVec::new([dst_offset, 0, 0]),
+                &CLVec::new([size, 1, 1]),
+            )
+        }),
     )
 
     // TODO
@@ -1662,18 +1671,57 @@ pub fn enqueue_write_image(
 }
 
 pub fn enqueue_copy_image(
-    _command_queue: cl_command_queue,
-    _src_image: cl_mem,
-    _dst_image: cl_mem,
-    _src_origin: *const usize,
-    _dst_origin: *const usize,
-    _region: *const usize,
-    _num_events_in_wait_list: cl_uint,
-    _event_wait_list: *const cl_event,
-    _event: *mut cl_event,
+    command_queue: cl_command_queue,
+    src_image: cl_mem,
+    dst_image: cl_mem,
+    src_origin: *const usize,
+    dst_origin: *const usize,
+    region: *const usize,
+    num_events_in_wait_list: cl_uint,
+    event_wait_list: *const cl_event,
+    event: *mut cl_event,
 ) -> CLResult<()> {
-    println!("enqueue_copy_image not implemented");
-    Err(CL_OUT_OF_HOST_MEMORY)
+    let q = command_queue.get_arc()?;
+    let src_image = src_image.get_arc()?;
+    let dst_image = dst_image.get_arc()?;
+    let evs = event_list_from_cl(&q, num_events_in_wait_list, event_wait_list)?;
+
+    // CL_INVALID_CONTEXT if the context associated with command_queue, src_image and dst_image are not the same
+    if src_image.context != q.context || dst_image.context != q.context {
+        return Err(CL_INVALID_CONTEXT);
+    }
+
+    // CL_IMAGE_FORMAT_MISMATCH if src_image and dst_image do not use the same image format.
+    if src_image.image_format != dst_image.image_format {
+        return Err(CL_IMAGE_FORMAT_MISMATCH);
+    }
+
+    // CL_INVALID_VALUE if src_origin, dst_origin, or region is NULL.
+    if src_origin.is_null() || dst_origin.is_null() || region.is_null() {
+        return Err(CL_INVALID_VALUE);
+    }
+
+    let region = unsafe { CLVec::from_raw(region) };
+    let dst_origin = unsafe { CLVec::from_raw(dst_origin) };
+    let src_origin = unsafe { CLVec::from_raw(src_origin) };
+
+    create_and_queue(
+        q,
+        CL_COMMAND_COPY_IMAGE,
+        evs,
+        event,
+        false,
+        Box::new(move |q, ctx| {
+            src_image.copy_to(q, ctx, &dst_image, src_origin, dst_origin, &region)
+        }),
+    )
+
+    //• CL_INVALID_VALUE if the 2D or 3D rectangular region specified by src_origin and src_origin + region refers to a region outside src_image, or if the 2D or 3D rectangular region specified by dst_origin and dst_origin + region refers to a region outside dst_image.
+    //• CL_INVALID_VALUE if values in src_origin, dst_origin and region do not follow rules described in the argument description for src_origin, dst_origin and region.
+    //• CL_INVALID_IMAGE_SIZE if image dimensions (image width, height, specified or compute row and/or slice pitch) for src_image or dst_image are not supported by device associated with queue.
+    //• CL_IMAGE_FORMAT_NOT_SUPPORTED if image format (image channel order and data type) for src_image or dst_image are not supported by device associated with queue.
+    //• CL_INVALID_OPERATION if the device associated with command_queue does not support images (i.e. CL_DEVICE_IMAGE_SUPPORT specified in the Device Queries table is CL_FALSE).
+    //• CL_MEM_COPY_OVERLAP if src_image and dst_image are the same image object and the source and destination regions overlap.
 }
 
 pub fn enqueue_fill_image(
index 14f442a..5f1856f 100644 (file)
@@ -78,6 +78,10 @@ pub struct CLVec<T> {
 }
 
 impl<T: Copy> CLVec<T> {
+    pub fn new(vals: [T; 3]) -> Self {
+        Self { vals: vals }
+    }
+
     /// # Safety
     ///
     /// This function is intended for use around OpenCL vectors of size 3.
@@ -112,6 +116,12 @@ impl<T> std::ops::Deref for CLVec<T> {
     }
 }
 
+impl<T> std::ops::DerefMut for CLVec<T> {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        &mut self.vals
+    }
+}
+
 impl<T: Copy + std::ops::Add<Output = T>> std::ops::Add for CLVec<T> {
     type Output = Self;
 
@@ -161,3 +171,21 @@ where
         self[0] * other[0] + self[1] * other[1] + self[2] * other[2]
     }
 }
+
+impl<S, T> TryInto<[T; 3]> for CLVec<S>
+where
+    S: Copy,
+    T: TryFrom<S>,
+    [T; 3]: TryFrom<Vec<T>>,
+{
+    type Error = cl_int;
+
+    fn try_into(self) -> Result<[T; 3], cl_int> {
+        let vec: Result<Vec<T>, _> = self
+            .vals
+            .iter()
+            .map(|v| T::try_from(*v).map_err(|_| CL_OUT_OF_HOST_MEMORY))
+            .collect();
+        vec?.try_into().map_err(|_| CL_OUT_OF_HOST_MEMORY)
+    }
+}
index bf6b287..30e4044 100644 (file)
@@ -463,25 +463,23 @@ impl Mem {
         q: &Arc<Queue>,
         ctx: &PipeContext,
         dst: &Arc<Mem>,
-        mut src_offset: usize,
-        mut dst_offset: usize,
-        size: usize,
+        mut src_origin: CLVec<usize>,
+        mut dst_origin: CLVec<usize>,
+        region: &CLVec<usize>,
     ) -> CLResult<()> {
-        assert!(self.is_buffer());
-
-        let src = self.to_parent(&mut src_offset);
-        let dst = dst.to_parent(&mut dst_offset);
+        let src = self.to_parent(&mut src_origin[0]);
+        let dst = dst.to_parent(&mut dst_origin[0]);
+        let bx = create_box(&src_origin, region, self.mem_type)?;
+        let mut dst_origin: [u32; 3] = dst_origin.try_into()?;
 
         let src_res = src.get_res()?.get(&q.device).unwrap();
         let dst_res = dst.get_res()?.get(&q.device).unwrap();
 
-        ctx.resource_copy_region(
-            src_res,
-            src_offset.try_into().map_err(|_| CL_OUT_OF_HOST_MEMORY)?,
-            dst_res,
-            dst_offset.try_into().map_err(|_| CL_OUT_OF_HOST_MEMORY)?,
-            size.try_into().map_err(|_| CL_OUT_OF_HOST_MEMORY)?,
-        );
+        if self.mem_type == CL_MEM_OBJECT_IMAGE1D_ARRAY {
+            (dst_origin[1], dst_origin[2]) = (dst_origin[2], dst_origin[1]);
+        }
+
+        ctx.resource_copy_region(src_res, dst_res, &dst_origin, &bx);
         Ok(())
     }
 
index 4ffca4b..b46f407 100644 (file)
@@ -105,30 +105,21 @@ impl PipeContext {
     pub fn resource_copy_region(
         &self,
         src: &PipeResource,
-        src_offset: i32,
         dst: &PipeResource,
-        dst_offset: u32,
-        size: i32,
+        dst_offset: &[u32; 3],
+        bx: &pipe_box,
     ) {
-        let b = pipe_box {
-            width: size,
-            height: 1,
-            depth: 1,
-            x: src_offset,
-            ..Default::default()
-        };
-
         unsafe {
             self.pipe.as_ref().resource_copy_region.unwrap()(
                 self.pipe.as_ptr(),
                 dst.pipe(),
                 0,
-                dst_offset,
-                0,
-                0,
+                dst_offset[0],
+                dst_offset[1],
+                dst_offset[2],
                 src.pipe(),
                 0,
-                &b,
+                bx,
             )
         }
     }