rusticl/mem: implement copy image

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>
This commit is contained in:
Karol Herbst 2022-03-24 18:21:44 +01:00 committed by Marge Bot
parent 490938e7dd
commit 5160bff15d
4 changed files with 106 additions and 41 deletions

View 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(

View 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)
}
}

View 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(())
}

View 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,
)
}
}