diff --git a/src/gallium/frontends/rusticl/api/icd.rs b/src/gallium/frontends/rusticl/api/icd.rs index 4f6f135787a..c915eae5248 100644 --- a/src/gallium/frontends/rusticl/api/icd.rs +++ b/src/gallium/frontends/rusticl/api/icd.rs @@ -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( diff --git a/src/gallium/frontends/rusticl/api/memory.rs b/src/gallium/frontends/rusticl/api/memory.rs index 3b54c4c14dc..f053587e91a 100644 --- a/src/gallium/frontends/rusticl/api/memory.rs +++ b/src/gallium/frontends/rusticl/api/memory.rs @@ -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, + ®ion, + 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, diff --git a/src/gallium/frontends/rusticl/core/memory.rs b/src/gallium/frontends/rusticl/core/memory.rs index 9a7757c2a39..9285bfefce1 100644 --- a/src/gallium/frontends/rusticl/core/memory.rs +++ b/src/gallium/frontends/rusticl/core/memory.rs @@ -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, + origin: &CLVec, + _region: &CLVec, + 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) }