From a7bf26c087831bddb43b42b756f1a500c5897029 Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Sat, 30 Apr 2022 22:34:02 +0200 Subject: [PATCH] rusticl/mem: implement clFillBuffer Signed-off-by: Karol Herbst Acked-by: Alyssa Rosenzweig Part-of: --- src/gallium/frontends/rusticl/api/icd.rs | 26 ++++++++- src/gallium/frontends/rusticl/api/memory.rs | 54 +++++++++++++++++++ src/gallium/frontends/rusticl/core/memory.rs | 19 +++++++ .../frontends/rusticl/mesa/pipe/context.rs | 14 +++++ 4 files changed, 112 insertions(+), 1 deletion(-) diff --git a/src/gallium/frontends/rusticl/api/icd.rs b/src/gallium/frontends/rusticl/api/icd.rs index 2e5896369f2..4844c238956 100644 --- a/src/gallium/frontends/rusticl/api/icd.rs +++ b/src/gallium/frontends/rusticl/api/icd.rs @@ -124,7 +124,7 @@ pub static DISPATCH: cl_icd_dispatch = cl_icd_dispatch { clLinkProgram: Some(cl_link_program), clUnloadPlatformCompiler: Some(cl_unload_platform_compiler), clGetKernelArgInfo: Some(cl_get_kernel_arg_info), - clEnqueueFillBuffer: None, + clEnqueueFillBuffer: Some(cl_enqueue_fill_buffer), clEnqueueFillImage: Some(cl_enqueue_fill_image), clEnqueueMigrateMemObjects: None, clEnqueueMarkerWithWaitList: None, @@ -1374,6 +1374,30 @@ extern "C" fn cl_get_kernel_arg_info( )) } +extern "C" fn cl_enqueue_fill_buffer( + command_queue: cl_command_queue, + buffer: cl_mem, + pattern: *const ::std::os::raw::c_void, + pattern_size: usize, + offset: usize, + cb: usize, + num_events_in_wait_list: cl_uint, + event_wait_list: *const cl_event, + event: *mut cl_event, +) -> cl_int { + match_err!(enqueue_fill_buffer( + command_queue, + buffer, + pattern, + pattern_size, + offset, + cb, + num_events_in_wait_list, + event_wait_list, + event, + )) +} + extern "C" fn cl_enqueue_fill_image( _command_queue: cl_command_queue, _image: cl_mem, diff --git a/src/gallium/frontends/rusticl/api/memory.rs b/src/gallium/frontends/rusticl/api/memory.rs index c4b9e1d043e..79762d0d15f 100644 --- a/src/gallium/frontends/rusticl/api/memory.rs +++ b/src/gallium/frontends/rusticl/api/memory.rs @@ -17,6 +17,7 @@ use self::rusticl_opencl_gen::*; use std::cmp::Ordering; use std::os::raw::c_void; use std::ptr; +use std::slice; use std::sync::Arc; fn validate_mem_flags(flags: cl_mem_flags, images: bool) -> CLResult<()> { @@ -1342,6 +1343,59 @@ pub fn enqueue_copy_buffer_rect( // CL_MISALIGNED_SUB_BUFFER_OFFSET if src_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_fill_buffer( + command_queue: cl_command_queue, + buffer: cl_mem, + pattern: *const ::std::os::raw::c_void, + pattern_size: usize, + offset: usize, + size: usize, + 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 evs = event_list_from_cl(&q, num_events_in_wait_list, event_wait_list)?; + + // CL_INVALID_VALUE if offset or offset + size require accessing elements outside the buffer + // buffer object respectively. + if offset + size > b.size { + return Err(CL_INVALID_VALUE); + } + + // CL_INVALID_VALUE if pattern is NULL or if pattern_size is 0 or if pattern_size is not one of + // { 1, 2, 4, 8, 16, 32, 64, 128 }. + if pattern.is_null() || pattern_size.count_ones() != 1 || pattern_size > 128 { + return Err(CL_INVALID_VALUE); + } + + // CL_INVALID_VALUE if offset and size are not a multiple of pattern_size. + if offset % pattern_size != 0 || size % pattern_size != 0 { + 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); + } + + // we have to copy memory + let pattern = unsafe { slice::from_raw_parts(pattern.cast(), pattern_size).to_vec() }; + create_and_queue( + q, + CL_COMMAND_FILL_BUFFER, + evs, + event, + false, + Box::new(move |q, ctx| b.fill(q, ctx, &pattern, offset, size)), + ) + + // 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. + //• CL_MEM_OBJECT_ALLOCATION_FAILURE if there is a failure to allocate memory for data store associated with buffer. +} + pub fn enqueue_map_buffer( command_queue: cl_command_queue, buffer: cl_mem, diff --git a/src/gallium/frontends/rusticl/core/memory.rs b/src/gallium/frontends/rusticl/core/memory.rs index 70508304a7b..2536bba93a3 100644 --- a/src/gallium/frontends/rusticl/core/memory.rs +++ b/src/gallium/frontends/rusticl/core/memory.rs @@ -285,6 +285,25 @@ impl Mem { Ok(()) } + pub fn fill( + &self, + q: &Arc, + ctx: &PipeContext, + pattern: &[u8], + mut offset: usize, + size: usize, + ) -> CLResult<()> { + let b = self.to_parent(&mut offset); + let res = b.get_res().get(&q.device).unwrap(); + ctx.clear_buffer( + res, + pattern, + offset.try_into().map_err(|_| CL_OUT_OF_HOST_MEMORY)?, + size.try_into().map_err(|_| CL_OUT_OF_HOST_MEMORY)?, + ); + Ok(()) + } + pub fn write_from_user_rect( &self, src: *const c_void, diff --git a/src/gallium/frontends/rusticl/mesa/pipe/context.rs b/src/gallium/frontends/rusticl/mesa/pipe/context.rs index 99a2718d206..42e68c6e28f 100644 --- a/src/gallium/frontends/rusticl/mesa/pipe/context.rs +++ b/src/gallium/frontends/rusticl/mesa/pipe/context.rs @@ -55,6 +55,19 @@ impl PipeContext { } } + pub fn clear_buffer(&self, res: &PipeResource, pattern: &[u8], offset: u32, size: u32) { + unsafe { + self.pipe.as_ref().clear_buffer.unwrap()( + self.pipe.as_ptr(), + res.pipe(), + offset, + size, + pattern.as_ptr().cast(), + pattern.len() as i32, + ) + } + } + pub fn resource_copy_region( &self, src: &PipeResource, @@ -236,6 +249,7 @@ fn has_required_cbs(c: &pipe_context) -> bool { && c.buffer_map.is_some() && c.buffer_subdata.is_some() && c.buffer_unmap.is_some() + && c.clear_buffer.is_some() && c.create_compute_state.is_some() && c.delete_compute_state.is_some() && c.flush.is_some()