rusticl/mem: implement maping images

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-23 23:12:36 +01:00
committed by Marge Bot
parent 0167cff815
commit ab24109eb5
3 changed files with 175 additions and 40 deletions

View File

@@ -1111,22 +1111,35 @@ extern "C" fn cl_enqueue_map_buffer(
}
extern "C" fn cl_enqueue_map_image(
_command_queue: cl_command_queue,
_image: cl_mem,
_blocking_map: cl_bool,
_map_flags: cl_map_flags,
_origin: *const usize,
_region: *const usize,
_image_row_pitch: *mut usize,
_image_slice_pitch: *mut usize,
_num_events_in_wait_list: cl_uint,
_event_wait_list: *const cl_event,
_event: *mut cl_event,
command_queue: cl_command_queue,
image: cl_mem,
blocking_map: cl_bool,
map_flags: cl_map_flags,
origin: *const usize,
region: *const usize,
image_row_pitch: *mut usize,
image_slice_pitch: *mut usize,
num_events_in_wait_list: cl_uint,
event_wait_list: *const cl_event,
event: *mut cl_event,
errcode_ret: *mut cl_int,
) -> *mut ::std::os::raw::c_void {
println!("cl_enqueue_map_image not implemented");
errcode_ret.write_checked(CL_OUT_OF_HOST_MEMORY);
ptr::null_mut()
match_obj!(
enqueue_map_image(
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
)
}
extern "C" fn cl_enqueue_unmap_mem_object(

View File

@@ -59,6 +59,34 @@ fn validate_mem_flags(flags: cl_mem_flags, images: bool) -> CLResult<()> {
Ok(())
}
fn validate_map_flags(m: &Mem, map_flags: cl_mem_flags) -> CLResult<()> {
// CL_INVALID_VALUE ... if values specified in map_flags are not valid.
let valid_flags =
cl_bitfield::from(CL_MAP_READ | CL_MAP_WRITE | CL_MAP_WRITE_INVALIDATE_REGION);
let read_write_group = cl_bitfield::from(CL_MAP_READ | CL_MAP_WRITE);
let invalidate_group = cl_bitfield::from(CL_MAP_WRITE_INVALIDATE_REGION);
if (map_flags & !valid_flags != 0)
|| ((map_flags & read_write_group != 0) && (map_flags & invalidate_group != 0))
{
return Err(CL_INVALID_VALUE);
}
// CL_INVALID_OPERATION if buffer has been created with CL_MEM_HOST_WRITE_ONLY or
// CL_MEM_HOST_NO_ACCESS and CL_MAP_READ is set in map_flags
if bit_check(m.flags, CL_MEM_HOST_WRITE_ONLY | CL_MEM_HOST_NO_ACCESS) &&
bit_check(map_flags, CL_MAP_READ) ||
// or if buffer has been created with CL_MEM_HOST_READ_ONLY or CL_MEM_HOST_NO_ACCESS and
// CL_MAP_WRITE or CL_MAP_WRITE_INVALIDATE_REGION is set in map_flags.
bit_check(m.flags, CL_MEM_HOST_READ_ONLY | CL_MEM_HOST_NO_ACCESS) &&
bit_check(map_flags, CL_MAP_WRITE | CL_MAP_WRITE_INVALIDATE_REGION)
{
return Err(CL_INVALID_OPERATION);
}
Ok(())
}
fn filter_image_access_flags(flags: cl_mem_flags) -> cl_mem_flags {
flags
& (CL_MEM_READ_WRITE | CL_MEM_WRITE_ONLY | CL_MEM_READ_ONLY | CL_MEM_KERNEL_READ_AND_WRITE)
@@ -1421,40 +1449,18 @@ pub fn enqueue_map_buffer(
event: *mut cl_event,
) -> CLResult<*mut c_void> {
let q = command_queue.get_arc()?;
let b = buffer.get_arc()?;
let b = buffer.get_ref()?;
let block = check_cl_bool(blocking_map).ok_or(CL_INVALID_VALUE)?;
let evs = event_list_from_cl(&q, num_events_in_wait_list, event_wait_list)?;
validate_map_flags(b, map_flags)?;
// CL_INVALID_VALUE if region being mapped given by (offset, size) is out of bounds or if size
// is 0
if offset + size > b.size || size == 0 {
return Err(CL_INVALID_VALUE);
}
// CL_INVALID_VALUE ... if values specified in map_flags are not valid.
let valid_flags =
cl_bitfield::from(CL_MAP_READ | CL_MAP_WRITE | CL_MAP_WRITE_INVALIDATE_REGION);
let read_write_group = cl_bitfield::from(CL_MAP_READ | CL_MAP_WRITE);
let invalidate_group = cl_bitfield::from(CL_MAP_WRITE_INVALIDATE_REGION);
if (map_flags & !valid_flags != 0)
|| ((map_flags & read_write_group != 0) && (map_flags & invalidate_group != 0))
{
return Err(CL_INVALID_VALUE);
}
// CL_INVALID_OPERATION if buffer has been created with CL_MEM_HOST_WRITE_ONLY or
// CL_MEM_HOST_NO_ACCESS and CL_MAP_READ is set in map_flags
if bit_check(b.flags, CL_MEM_HOST_WRITE_ONLY | CL_MEM_HOST_NO_ACCESS) &&
bit_check(map_flags, CL_MAP_READ) ||
// or if buffer has been created with CL_MEM_HOST_READ_ONLY or CL_MEM_HOST_NO_ACCESS and
// CL_MAP_WRITE or CL_MAP_WRITE_INVALIDATE_REGION is set in map_flags.
bit_check(b.flags, CL_MEM_HOST_READ_ONLY | CL_MEM_HOST_NO_ACCESS) &&
bit_check(map_flags, CL_MAP_WRITE | CL_MAP_WRITE_INVALIDATE_REGION)
{
return Err(CL_INVALID_OPERATION);
}
// CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST if the map operation is 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()) {
@@ -1670,6 +1676,80 @@ pub fn enqueue_copy_image(
Err(CL_OUT_OF_HOST_MEMORY)
}
pub fn enqueue_map_image(
command_queue: cl_command_queue,
image: cl_mem,
blocking_map: cl_bool,
map_flags: cl_map_flags,
origin: *const usize,
region: *const usize,
image_row_pitch: *mut usize,
image_slice_pitch: *mut usize,
num_events_in_wait_list: cl_uint,
event_wait_list: *const cl_event,
event: *mut cl_event,
) -> CLResult<*mut ::std::os::raw::c_void> {
let q = command_queue.get_arc()?;
let i = image.get_ref()?;
let block = check_cl_bool(blocking_map).ok_or(CL_INVALID_VALUE)?;
let evs = event_list_from_cl(&q, num_events_in_wait_list, event_wait_list)?;
validate_map_flags(i, map_flags)?;
// CL_INVALID_CONTEXT if context associated with command_queue and image are not the same
if i.context != q.context {
return Err(CL_INVALID_CONTEXT);
}
// CL_INVALID_VALUE if origin or region is NULL.
// CL_INVALID_VALUE if image_row_pitch is NULL.
if origin.is_null() || region.is_null() || image_row_pitch.is_null() {
return Err(CL_INVALID_VALUE);
}
let region = unsafe { CLVec::from_raw(region) };
let origin = unsafe { CLVec::from_raw(origin) };
create_and_queue(
q.clone(),
CL_COMMAND_MAP_IMAGE,
evs,
event,
block,
// we don't really have anything to do here?
Box::new(|_, _| Ok(())),
)?;
let mut dummy_slice_pitch: usize = 0;
let image_slice_pitch = if image_slice_pitch.is_null() {
// CL_INVALID_VALUE if image is a 3D image, 1D or 2D image array object and
// image_slice_pitch is NULL.
if i.image_desc.is_array() || i.image_desc.image_type == CL_MEM_OBJECT_IMAGE3D {
return Err(CL_INVALID_VALUE);
}
&mut dummy_slice_pitch
} else {
unsafe { image_slice_pitch.as_mut().unwrap() }
};
i.map_image(
&q,
&origin,
&region,
unsafe { image_row_pitch.as_mut().unwrap() },
image_slice_pitch,
block,
)
//• CL_INVALID_VALUE if region being mapped given by (origin, origin + region) is out of bounds or if values specified in map_flags are not valid.
//• CL_INVALID_VALUE if values in origin and region do not follow rules described in the argument description for origin and region.
//• CL_INVALID_IMAGE_SIZE if image dimensions (image width, height, specified or compute row and/or slice pitch) for image are not supported by device associated with queue.
//• CL_IMAGE_FORMAT_NOT_SUPPORTED if image format (image channel order and data type) for image are not supported by device associated with queue.
//• CL_MAP_FAILURE if there is a failure to map the requested region into the host address space. This error cannot occur for image objects created with CL_MEM_USE_HOST_PTR or CL_MEM_ALLOC_HOST_PTR.
//• CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST if the map operation is blocking and the execution status of any of the events in event_wait_list is a negative integer value.
//• 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_INVALID_OPERATION if mapping would lead to overlapping regions being mapped for writing.
}
pub fn enqueue_unmap_mem_object(
command_queue: cl_command_queue,
memobj: cl_mem,

View File

@@ -649,7 +649,13 @@ impl Mem {
block: bool,
) -> CLResult<&'a PipeTransfer> {
if !lock.tx.contains_key(&q.device) {
let tx = self.tx(q, ctx, 0, self.size, block)?;
let tx = if self.is_buffer() {
self.tx(q, ctx, 0, self.size, block)?
} else {
let bx = self.image_desc.bx()?;
self.tx_image(q, ctx, &bx, block)?
};
lock.tx.insert(q.device.clone(), (tx, 0));
}
@@ -681,6 +687,42 @@ impl Mem {
Ok(ptr)
}
pub fn map_image(
&self,
q: &Arc<Queue>,
origin: &CLVec<usize>,
_region: &CLVec<usize>,
row_pitch: &mut usize,
slice_pitch: &mut usize,
block: bool,
) -> CLResult<*mut c_void> {
assert!(!self.is_buffer());
let mut lock = self.maps.lock().unwrap();
let tx = self.map(q, &q.device.helper_ctx(), &mut lock, block)?;
*row_pitch = tx.row_pitch() as usize;
*slice_pitch = tx.slice_pitch() as usize;
let ptr = unsafe {
tx.ptr().add(
*origin
* [
self.image_format.pixel_size().unwrap() as usize,
*row_pitch,
*slice_pitch,
],
)
};
if let Some(e) = lock.maps.get_mut(&ptr) {
*e += 1;
} else {
lock.maps.insert(ptr, 1);
}
Ok(ptr)
}
pub fn is_mapped_ptr(&self, ptr: *mut c_void) -> bool {
self.maps.lock().unwrap().maps.contains_key(&ptr)
}