Module: Mesa Branch: main Commit: 2645003bdc527b5dc046366fce5e65b44b27334f URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=2645003bdc527b5dc046366fce5e65b44b27334f
Author: Antonio Gomes <antoniospg...@gmail.com> Date: Sat Aug 12 22:50:55 2023 -0300 rusticl: Create CL mem objects from GL Reviewed-by: Karol Herbst <kher...@redhat.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21305> --- src/gallium/frontends/rusticl/api/icd.rs | 27 ++- src/gallium/frontends/rusticl/api/memory.rs | 217 ++++++++++++++++++++++ src/gallium/frontends/rusticl/core/context.rs | 34 ++++ src/gallium/frontends/rusticl/core/gl.rs | 206 +++++++++++++++++++- src/gallium/frontends/rusticl/core/memory.rs | 73 ++++++++ src/gallium/frontends/rusticl/core/util.rs | 1 + src/gallium/frontends/rusticl/mesa/pipe/screen.rs | 37 ++++ 7 files changed, 585 insertions(+), 10 deletions(-) diff --git a/src/gallium/frontends/rusticl/api/icd.rs b/src/gallium/frontends/rusticl/api/icd.rs index 29fbbf4015b..bd033e5abb9 100644 --- a/src/gallium/frontends/rusticl/api/icd.rs +++ b/src/gallium/frontends/rusticl/api/icd.rs @@ -85,14 +85,14 @@ pub static DISPATCH: cl_icd_dispatch = cl_icd_dispatch { clEnqueueWaitForEvents: None, clEnqueueBarrier: Some(cl_enqueue_barrier), clGetExtensionFunctionAddress: Some(cl_get_extension_function_address), - clCreateFromGLBuffer: None, - clCreateFromGLTexture2D: None, - clCreateFromGLTexture3D: None, - clCreateFromGLRenderbuffer: None, - clGetGLObjectInfo: None, - clGetGLTextureInfo: None, - clEnqueueAcquireGLObjects: None, - clEnqueueReleaseGLObjects: None, + clCreateFromGLBuffer: Some(cl_create_from_gl_buffer), + clCreateFromGLTexture2D: Some(cl_create_from_gl_texture_2d), + clCreateFromGLTexture3D: Some(cl_create_from_gl_texture_3d), + clCreateFromGLRenderbuffer: Some(cl_create_from_gl_renderbuffer), + clGetGLObjectInfo: Some(cl_get_gl_object_info), + clGetGLTextureInfo: Some(cl_get_gl_texture_info), + clEnqueueAcquireGLObjects: Some(cl_enqueue_acquire_gl_objects), + clEnqueueReleaseGLObjects: Some(cl_enqueue_release_gl_objects), clGetGLContextInfoKHR: Some(cl_get_gl_context_info_khr), clGetDeviceIDsFromD3D10KHR: ptr::null_mut(), clCreateFromD3D10BufferKHR: ptr::null_mut(), @@ -127,7 +127,7 @@ pub static DISPATCH: cl_icd_dispatch = cl_icd_dispatch { clEnqueueMarkerWithWaitList: Some(cl_enqueue_marker_with_wait_list), clEnqueueBarrierWithWaitList: Some(cl_enqueue_barrier_with_wait_list), clGetExtensionFunctionAddressForPlatform: Some(cl_get_extension_function_address_for_platform), - clCreateFromGLTexture: None, + clCreateFromGLTexture: Some(cl_create_from_gl_texture), clGetDeviceIDsFromD3D11KHR: ptr::null_mut(), clCreateFromD3D11BufferKHR: ptr::null_mut(), clCreateFromD3D11Texture2DKHR: ptr::null_mut(), @@ -414,7 +414,16 @@ extern "C" fn cl_get_extension_function_address( "clCreateProgramWithILKHR" => cl_create_program_with_il as *mut ::std::ffi::c_void, // cl_khr_gl_sharing + "clCreateFromGLBuffer" => cl_create_from_gl_buffer as *mut ::std::ffi::c_void, + "clCreateFromGLRenderbuffer" => cl_create_from_gl_renderbuffer as *mut ::std::ffi::c_void, + "clCreateFromGLTexture" => cl_create_from_gl_texture as *mut ::std::ffi::c_void, + "clCreateFromGLTexture2D" => cl_create_from_gl_texture_2d as *mut ::std::ffi::c_void, + "clCreateFromGLTexture3D" => cl_create_from_gl_texture_3d as *mut ::std::ffi::c_void, + "clEnqueueAcquireGLObjects" => cl_enqueue_acquire_gl_objects as *mut ::std::ffi::c_void, + "clEnqueueReleaseGLObjects" => cl_enqueue_release_gl_objects as *mut ::std::ffi::c_void, "clGetGLContextInfoKHR" => cl_get_gl_context_info_khr as *mut ::std::ffi::c_void, + "clGetGLObjectInfo" => cl_get_gl_object_info as *mut ::std::ffi::c_void, + "clGetGLTextureInfo" => cl_get_gl_texture_info as *mut ::std::ffi::c_void, // cl_arm_shared_virtual_memory "clEnqueueSVMFreeARM" => cl_enqueue_svm_free_arm as *mut ::std::ffi::c_void, diff --git a/src/gallium/frontends/rusticl/api/memory.rs b/src/gallium/frontends/rusticl/api/memory.rs index 33941eb6298..d8c4f09fab0 100644 --- a/src/gallium/frontends/rusticl/api/memory.rs +++ b/src/gallium/frontends/rusticl/api/memory.rs @@ -7,6 +7,7 @@ use crate::api::util::*; use crate::core::context::Context; use crate::core::device::*; use crate::core::format::*; +use crate::core::gl::*; use crate::core::memory::*; use mesa_rust_util::properties::Properties; @@ -2887,3 +2888,219 @@ fn create_pipe( ) -> CLResult<cl_mem> { Err(CL_INVALID_OPERATION) } + +#[cl_info_entrypoint(cl_get_gl_texture_info)] +impl CLInfo<cl_gl_texture_info> for cl_mem { + fn query(&self, q: cl_gl_texture_info, _: &[u8]) -> CLResult<Vec<MaybeUninit<u8>>> { + let mem = self.get_ref()?; + Ok(match *q { + CL_GL_MIPMAP_LEVEL => cl_prop::<cl_GLint>(0), + CL_GL_TEXTURE_TARGET => cl_prop::<cl_GLenum>( + mem.gl_obj + .as_ref() + .ok_or(CL_INVALID_GL_OBJECT)? + .gl_object_target, + ), + _ => return Err(CL_INVALID_VALUE), + }) + } +} + +fn create_from_gl( + context: cl_context, + flags: cl_mem_flags, + target: cl_GLenum, + miplevel: cl_GLint, + texture: cl_GLuint, +) -> CLResult<cl_mem> { + let c = context.get_arc()?; + let gl_ctx_manager = &c.gl_ctx_manager; + + // CL_INVALID_CONTEXT if context associated with command_queue was not created from an OpenGL context + if gl_ctx_manager.is_none() { + return Err(CL_INVALID_CONTEXT); + } + + // CL_INVALID_VALUE if values specified in flags are not valid or if value specified in + // texture_target is not one of the values specified in the description of texture_target. + validate_mem_flags(flags, target == GL_ARRAY_BUFFER)?; + + // CL_INVALID_MIP_LEVEL if miplevel is greather than zero and the OpenGL + // implementation does not support creating from non-zero mipmap levels. + if miplevel > 0 { + return Err(CL_INVALID_MIP_LEVEL); + } + + // CL_INVALID_CONTEXT if context [..] was not created from a GL context. + if let Some(gl_ctx_manager) = gl_ctx_manager { + let gl_export_manager = + gl_ctx_manager.export_object(target, flags as u32, miplevel, texture)?; + + Ok(cl_mem::from_arc(Mem::from_gl( + c, + flags, + &gl_export_manager, + )?)) + } else { + Err(CL_INVALID_CONTEXT) + } +} + +#[cl_entrypoint] +fn create_from_gl_texture( + context: cl_context, + flags: cl_mem_flags, + target: cl_GLenum, + miplevel: cl_GLint, + texture: cl_GLuint, +) -> CLResult<cl_mem> { + // CL_INVALID_VALUE if values specified in flags are not valid or if value specified in + // texture_target is not one of the values specified in the description of texture_target. + if !is_valid_gl_texture(target) { + return Err(CL_INVALID_VALUE); + } + + create_from_gl(context, flags, target, miplevel, texture) +} + +#[cl_entrypoint] +fn create_from_gl_texture_2d( + context: cl_context, + flags: cl_mem_flags, + target: cl_GLenum, + miplevel: cl_GLint, + texture: cl_GLuint, +) -> CLResult<cl_mem> { + // CL_INVALID_VALUE if values specified in flags are not valid or if value specified in + // texture_target is not one of the values specified in the description of texture_target. + if !is_valid_gl_texture_2d(target) { + return Err(CL_INVALID_VALUE); + } + + create_from_gl(context, flags, target, miplevel, texture) +} + +#[cl_entrypoint] +fn create_from_gl_texture_3d( + context: cl_context, + flags: cl_mem_flags, + target: cl_GLenum, + miplevel: cl_GLint, + texture: cl_GLuint, +) -> CLResult<cl_mem> { + // CL_INVALID_VALUE if values specified in flags are not valid or if value specified in + // texture_target is not one of the values specified in the description of texture_target. + if target != GL_TEXTURE_3D { + return Err(CL_INVALID_VALUE); + } + + create_from_gl(context, flags, target, miplevel, texture) +} + +#[cl_entrypoint] +fn create_from_gl_buffer( + context: cl_context, + flags: cl_mem_flags, + bufobj: cl_GLuint, +) -> CLResult<cl_mem> { + create_from_gl(context, flags, GL_ARRAY_BUFFER, 0, bufobj) +} + +#[cl_entrypoint] +fn create_from_gl_renderbuffer( + context: cl_context, + flags: cl_mem_flags, + renderbuffer: cl_GLuint, +) -> CLResult<cl_mem> { + create_from_gl(context, flags, GL_RENDERBUFFER, 0, renderbuffer) +} + +#[cl_entrypoint] +fn get_gl_object_info( + memobj: cl_mem, + gl_object_type: *mut cl_gl_object_type, + gl_object_name: *mut cl_GLuint, +) -> CLResult<()> { + let m = memobj.get_ref()?; + + match &m.gl_obj { + Some(gl_obj) => { + gl_object_type.write_checked(gl_obj.gl_object_type); + gl_object_name.write_checked(gl_obj.gl_object_name); + } + None => { + // CL_INVALID_GL_OBJECT if there is no GL object associated with memobj. + return Err(CL_INVALID_GL_OBJECT); + } + } + + Ok(()) +} + +#[cl_entrypoint] +fn enqueue_acquire_gl_objects( + command_queue: cl_command_queue, + num_objects: cl_uint, + mem_objects: *const cl_mem, + 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 evs = event_list_from_cl(&q, num_events_in_wait_list, event_wait_list)?; + let objs = cl_mem::get_arc_vec_from_arr(mem_objects, num_objects)?; + let gl_ctx_manager = &q.context.gl_ctx_manager; + + // CL_INVALID_CONTEXT if context associated with command_queue was not created from an OpenGL context + if gl_ctx_manager.is_none() { + return Err(CL_INVALID_CONTEXT); + } + + // CL_INVALID_GL_OBJECT if memory objects in mem_objects have not been created from a GL object(s). + if objs.iter().any(|o| o.gl_obj.is_none()) { + return Err(CL_INVALID_GL_OBJECT); + } + + create_and_queue( + q, + CL_COMMAND_ACQUIRE_GL_OBJECTS, + evs, + event, + false, + Box::new(|_, _| Ok(())), + ) +} + +#[cl_entrypoint] +fn enqueue_release_gl_objects( + command_queue: cl_command_queue, + num_objects: cl_uint, + mem_objects: *const cl_mem, + 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 evs = event_list_from_cl(&q, num_events_in_wait_list, event_wait_list)?; + let objs = cl_mem::get_arc_vec_from_arr(mem_objects, num_objects)?; + let gl_ctx_manager = &q.context.gl_ctx_manager; + + // CL_INVALID_CONTEXT if context associated with command_queue was not created from an OpenGL context + if gl_ctx_manager.is_none() { + return Err(CL_INVALID_CONTEXT); + } + + // CL_INVALID_GL_OBJECT if memory objects in mem_objects have not been created from a GL object(s). + if objs.iter().any(|o| o.gl_obj.is_none()) { + return Err(CL_INVALID_GL_OBJECT); + } + + create_and_queue( + q, + CL_COMMAND_RELEASE_GL_OBJECTS, + evs, + event, + false, + Box::new(move |_, _| Ok(())), + ) +} diff --git a/src/gallium/frontends/rusticl/core/context.rs b/src/gallium/frontends/rusticl/core/context.rs index e475374ef0f..b9e518fe35f 100644 --- a/src/gallium/frontends/rusticl/core/context.rs +++ b/src/gallium/frontends/rusticl/core/context.rs @@ -9,6 +9,7 @@ use crate::impl_cl_type_trait; use mesa_rust::pipe::resource::*; use mesa_rust::pipe::screen::ResourceType; +use mesa_rust_gen::pipe_format; use mesa_rust_util::properties::Properties; use rusticl_opencl_gen::*; @@ -204,6 +205,39 @@ impl Context { pub fn remove_svm_ptr(&self, ptr: *const c_void) -> Option<Layout> { self.svm_ptrs.lock().unwrap().remove(&ptr) } + + pub fn import_gl_buffer( + &self, + handle: u32, + modifier: u64, + image_type: cl_mem_object_type, + format: pipe_format, + gl_props: GLMemProps, + ) -> CLResult<HashMap<&'static Device, Arc<PipeResource>>> { + let mut res = HashMap::new(); + let target = cl_mem_type_to_texture_target(image_type); + + for dev in &self.devs { + let resource = dev + .screen() + .resource_import_dmabuf( + handle, + modifier, + target, + format, + gl_props.stride, + gl_props.width, + gl_props.height, + gl_props.depth, + gl_props.array_size, + ) + .ok_or(CL_OUT_OF_RESOURCES)?; + + res.insert(*dev, Arc::new(resource)); + } + + Ok(res) + } } impl Drop for Context { diff --git a/src/gallium/frontends/rusticl/core/gl.rs b/src/gallium/frontends/rusticl/core/gl.rs index 3a0e4491b71..10eee45ee80 100644 --- a/src/gallium/frontends/rusticl/core/gl.rs +++ b/src/gallium/frontends/rusticl/core/gl.rs @@ -1,6 +1,7 @@ use crate::api::icd::*; +use crate::core::format::*; -use libc_rust_gen::dlsym; +use libc_rust_gen::{close, dlsym}; use rusticl_opencl_gen::*; use std::ffi::CString; @@ -166,6 +167,153 @@ impl GLCtxManager { Err(CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR) } } + + pub fn export_object( + &self, + target: cl_GLenum, + flags: u32, + miplevel: cl_GLint, + texture: cl_GLuint, + ) -> CLResult<GLExportManager> { + let xplat_manager = &self.xplat_manager; + let mut export_in = mesa_glinterop_export_in { + version: 1, + target: target, + obj: texture, + miplevel: miplevel as u32, + access: cl_to_interop_flags(flags), + ..Default::default() + }; + + let mut export_out = mesa_glinterop_export_out { + version: 2, + ..Default::default() + }; + + let err = unsafe { + match &self.gl_ctx { + GLCtx::EGL(disp, ctx) => { + let egl_export_object_func = xplat_manager + .MesaGLInteropEGLExportObject()? + .ok_or(CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR)?; + + egl_export_object_func(disp.cast(), ctx.cast(), &mut export_in, &mut export_out) + } + GLCtx::GLX(disp, ctx) => { + let glx_export_object_func = xplat_manager + .MesaGLInteropGLXExportObject()? + .ok_or(CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR)?; + + glx_export_object_func(disp.cast(), ctx.cast(), &mut export_in, &mut export_out) + } + } + }; + + if err != MESA_GLINTEROP_SUCCESS as i32 { + return Err(interop_to_cl_error(err)); + } + + // CL_INVALID_GL_OBJECT if bufobj is not a GL buffer object or is a GL buffer + // object but does not have an existing data store or the size of the buffer is 0. + if target == GL_ARRAY_BUFFER && export_out.buf_size == 0 { + return Err(CL_INVALID_GL_OBJECT); + } + + Ok(GLExportManager { + export_in: export_in, + export_out: export_out, + }) + } +} + +#[derive(Clone)] +pub struct GLMemProps { + pub height: u16, + pub depth: u16, + pub width: u32, + pub array_size: u16, + pub pixel_size: u8, + pub stride: u32, +} + +impl GLMemProps { + pub fn size(&self) -> usize { + self.height as usize + * self.depth as usize + * self.array_size as usize + * self.width as usize + * self.pixel_size as usize + } +} + +pub struct GLExportManager { + pub export_in: mesa_glinterop_export_in, + pub export_out: mesa_glinterop_export_out, +} + +impl GLExportManager { + pub fn get_gl_mem_props(&self) -> CLResult<GLMemProps> { + let pixel_size = if self.is_gl_buffer() { + 0 + } else { + format_from_gl(self.export_out.internal_format) + .ok_or(CL_OUT_OF_HOST_MEMORY)? + .pixel_size() + .unwrap() + }; + + let mut height = self.export_out.height as u16; + let mut depth = self.export_out.depth as u16; + let mut width = self.export_out.width; + let mut array_size = 1; + + // some fixups + match self.export_in.target { + GL_TEXTURE_1D_ARRAY => { + array_size = height; + height = 1; + depth = 1; + } + GL_TEXTURE_2D_ARRAY => { + array_size = depth; + depth = 1; + } + GL_ARRAY_BUFFER => { + array_size = 1; + width = self.export_out.buf_size as u32; + height = 1; + depth = 1; + } + _ => {} + } + + Ok(GLMemProps { + height: height, + depth: depth, + width: width, + array_size: array_size, + pixel_size: pixel_size, + stride: self.export_out.stride, + }) + } + + pub fn is_gl_buffer(&self) -> bool { + self.export_out.internal_format == GL_NONE + } +} + +impl Drop for GLExportManager { + fn drop(&mut self) { + unsafe { + close(self.export_out.dmabuf_fd); + } + } +} + +pub struct GLObject { + pub gl_object_target: cl_GLenum, + pub gl_object_type: cl_gl_object_type, + pub gl_object_name: cl_GLuint, } pub fn interop_to_cl_error(error: i32) -> CLError { @@ -181,3 +329,59 @@ pub fn interop_to_cl_error(error: i32) -> CLError { _ => CL_OUT_OF_HOST_MEMORY, } } + +pub fn cl_to_interop_flags(flags: u32) -> u32 { + match flags { + CL_MEM_READ_WRITE => MESA_GLINTEROP_ACCESS_READ_WRITE, + CL_MEM_READ_ONLY => MESA_GLINTEROP_ACCESS_READ_ONLY, + CL_MEM_WRITE_ONLY => MESA_GLINTEROP_ACCESS_WRITE_ONLY, + _ => 0, + } +} + +pub fn target_from_gl(target: u32) -> CLResult<(u32, u32)> { + // CL_INVALID_IMAGE_FORMAT_DESCRIPTOR if the OpenGL texture + // internal format does not map to a supported OpenCL image format. + Ok(match target { + GL_ARRAY_BUFFER => (CL_MEM_OBJECT_BUFFER, CL_GL_OBJECT_BUFFER), + GL_RENDERBUFFER => (CL_MEM_OBJECT_IMAGE2D, CL_GL_OBJECT_RENDERBUFFER), + GL_TEXTURE_1D => (CL_MEM_OBJECT_IMAGE1D, CL_GL_OBJECT_TEXTURE1D), + GL_TEXTURE_1D_ARRAY => (CL_MEM_OBJECT_IMAGE1D_ARRAY, CL_GL_OBJECT_TEXTURE1D_ARRAY), + GL_TEXTURE_CUBE_MAP_NEGATIVE_X + | GL_TEXTURE_CUBE_MAP_NEGATIVE_Y + | GL_TEXTURE_CUBE_MAP_NEGATIVE_Z + | GL_TEXTURE_CUBE_MAP_POSITIVE_X + | GL_TEXTURE_CUBE_MAP_POSITIVE_Y + | GL_TEXTURE_CUBE_MAP_POSITIVE_Z + | GL_TEXTURE_2D + | GL_TEXTURE_RECTANGLE => (CL_MEM_OBJECT_IMAGE2D, CL_GL_OBJECT_TEXTURE2D), + GL_TEXTURE_2D_ARRAY => (CL_MEM_OBJECT_IMAGE2D_ARRAY, CL_GL_OBJECT_TEXTURE2D_ARRAY), + GL_TEXTURE_3D => (CL_MEM_OBJECT_IMAGE3D, CL_GL_OBJECT_TEXTURE3D), + _ => return Err(CL_INVALID_VALUE), + }) +} + +pub fn is_valid_gl_texture(target: u32) -> bool { + matches!( + target, + GL_TEXTURE_1D + | GL_TEXTURE_1D_ARRAY + | GL_TEXTURE_BUFFER + | GL_TEXTURE_2D_ARRAY + | GL_TEXTURE_3D + ) || is_valid_gl_texture_2d(target) +} + +pub fn is_valid_gl_texture_2d(target: u32) -> bool { + matches!( + target, + GL_TEXTURE_2D + | GL_TEXTURE_RECTANGLE + | GL_TEXTURE_CUBE_MAP_NEGATIVE_X + | GL_TEXTURE_CUBE_MAP_NEGATIVE_Y + | GL_TEXTURE_CUBE_MAP_NEGATIVE_Z + | GL_TEXTURE_CUBE_MAP_POSITIVE_X + | GL_TEXTURE_CUBE_MAP_POSITIVE_Y + | GL_TEXTURE_CUBE_MAP_POSITIVE_Z + ) +} diff --git a/src/gallium/frontends/rusticl/core/memory.rs b/src/gallium/frontends/rusticl/core/memory.rs index ec7f3bb96a3..7ab9cb870de 100644 --- a/src/gallium/frontends/rusticl/core/memory.rs +++ b/src/gallium/frontends/rusticl/core/memory.rs @@ -4,6 +4,7 @@ use crate::api::util::*; use crate::core::context::*; use crate::core::device::*; use crate::core::format::*; +use crate::core::gl::*; use crate::core::queue::*; use crate::core::util::*; use crate::impl_cl_type_trait; @@ -118,6 +119,7 @@ pub struct Mem { pub image_elem_size: u8, pub props: Vec<cl_mem_properties>, pub cbs: Mutex<Vec<MemCB>>, + pub gl_obj: Option<GLObject>, res: Option<HashMap<&'static Device, Arc<PipeResource>>>, maps: Mutex<Mappings>, } @@ -306,6 +308,7 @@ impl Mem { image_desc: cl_image_desc::default(), image_elem_size: 0, props: props, + gl_obj: None, cbs: Mutex::new(Vec::new()), res: Some(buffer), maps: Mappings::new(), @@ -338,6 +341,7 @@ impl Mem { image_desc: cl_image_desc::default(), image_elem_size: 0, props: Vec::new(), + gl_obj: None, cbs: Mutex::new(Vec::new()), res: None, maps: Mappings::new(), @@ -422,12 +426,81 @@ impl Mem { image_desc: api_image_desc, image_elem_size: image_elem_size, props: props, + gl_obj: None, cbs: Mutex::new(Vec::new()), res: texture, maps: Mappings::new(), })) } + pub fn from_gl( + context: Arc<Context>, + flags: cl_mem_flags, + gl_export_manager: &GLExportManager, + ) -> CLResult<Arc<Mem>> { + let export_in = &gl_export_manager.export_in; + let export_out = &gl_export_manager.export_out; + + let (mem_type, gl_object_type) = target_from_gl(export_in.target)?; + let gl_mem_props = gl_export_manager.get_gl_mem_props()?; + + // Handle Buffers + let (image_format, pipe_format) = if gl_export_manager.is_gl_buffer() { + (cl_image_format::default(), pipe_format::PIPE_FORMAT_NONE) + } else { + let image_format = + format_from_gl(export_out.internal_format).ok_or(CL_OUT_OF_HOST_MEMORY)?; + (image_format, image_format.to_pipe_format().unwrap()) + }; + + let texture = context.import_gl_buffer( + export_out.dmabuf_fd as u32, + export_out.modifier, + mem_type, + pipe_format, + gl_mem_props.clone(), + )?; + + let gl_obj = GLObject { + gl_object_target: gl_export_manager.export_in.target, + gl_object_type: gl_object_type, + gl_object_name: export_in.obj, + }; + + let desc = cl_image_desc { + image_type: mem_type, + image_width: gl_mem_props.width as usize, + image_height: gl_mem_props.height as usize, + image_depth: gl_mem_props.depth as usize, + image_array_size: gl_mem_props.array_size as usize, + image_row_pitch: 0, + image_slice_pitch: 0, + num_mip_levels: 1, + num_samples: 1, + ..Default::default() + }; + + Ok(Arc::new(Self { + base: CLObjectBase::new(), + context: context, + parent: None, + mem_type: mem_type, + flags: flags, + size: gl_mem_props.size(), + offset: 0, + host_ptr: ptr::null_mut(), + image_format: image_format, + pipe_format: pipe_format, + image_desc: desc, + image_elem_size: gl_mem_props.pixel_size, + props: Vec::new(), + gl_obj: Some(gl_obj), + cbs: Mutex::new(Vec::new()), + res: Some(texture), + maps: Mappings::new(), + })) + } + pub fn pixel_size(&self) -> Option<u8> { if self.is_buffer() { Some(1) diff --git a/src/gallium/frontends/rusticl/core/util.rs b/src/gallium/frontends/rusticl/core/util.rs index 27f03d7303b..8bb42184a41 100644 --- a/src/gallium/frontends/rusticl/core/util.rs +++ b/src/gallium/frontends/rusticl/core/util.rs @@ -7,6 +7,7 @@ use std::mem; pub fn cl_mem_type_to_texture_target(mem_type: cl_mem_object_type) -> pipe_texture_target { match mem_type { + CL_MEM_OBJECT_BUFFER => pipe_texture_target::PIPE_BUFFER, CL_MEM_OBJECT_IMAGE1D => pipe_texture_target::PIPE_TEXTURE_1D, CL_MEM_OBJECT_IMAGE2D => pipe_texture_target::PIPE_TEXTURE_2D, CL_MEM_OBJECT_IMAGE3D => pipe_texture_target::PIPE_TEXTURE_3D, diff --git a/src/gallium/frontends/rusticl/mesa/pipe/screen.rs b/src/gallium/frontends/rusticl/mesa/pipe/screen.rs index bcac249cefc..427ecc982f9 100644 --- a/src/gallium/frontends/rusticl/mesa/pipe/screen.rs +++ b/src/gallium/frontends/rusticl/mesa/pipe/screen.rs @@ -225,6 +225,43 @@ impl PipeScreen { self.resource_create_from_user(&tmpl, mem) } + pub fn resource_import_dmabuf( + &self, + handle: u32, + modifier: u64, + target: pipe_texture_target, + format: pipe_format, + stride: u32, + width: u32, + height: u16, + depth: u16, + array_size: u16, + ) -> Option<PipeResource> { + let mut tmpl = pipe_resource::default(); + let mut handle = winsys_handle { + type_: WINSYS_HANDLE_TYPE_FD, + handle: handle, + modifier: modifier, + format: format as u64, + stride: stride, + ..Default::default() + }; + + tmpl.set_target(target); + tmpl.set_format(format); + tmpl.width0 = width; + tmpl.height0 = height; + tmpl.depth0 = depth; + tmpl.array_size = array_size; + + unsafe { + PipeResource::new( + (*self.screen).resource_from_handle.unwrap()(self.screen, &tmpl, &mut handle, 0), + false, + ) + } + } + pub fn param(&self, cap: pipe_cap) -> i32 { unsafe { (*self.screen).get_param.unwrap()(self.screen, cap) } }