Module: Mesa Branch: main Commit: 1c3dde7ba6028c62a2489b46467cbfdf1e78a5c1 URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=1c3dde7ba6028c62a2489b46467cbfdf1e78a5c1
Author: Antonio Gomes <antoniospg...@gmail.com> Date: Fri Apr 21 21:41:25 2023 -0300 rusticl: Add support for cube maps Reviewed-by: Karol Herbst <kher...@redhat.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21305> --- src/gallium/frontends/rusticl/api/memory.rs | 4 +- src/gallium/frontends/rusticl/core/device.rs | 10 ++ src/gallium/frontends/rusticl/core/gl.rs | 129 +++++++++++++++++++++ src/gallium/frontends/rusticl/core/memory.rs | 22 +++- .../frontends/rusticl/mesa/pipe/resource.rs | 1 + 5 files changed, 163 insertions(+), 3 deletions(-) diff --git a/src/gallium/frontends/rusticl/api/memory.rs b/src/gallium/frontends/rusticl/api/memory.rs index d8c4f09fab0..c3216b28055 100644 --- a/src/gallium/frontends/rusticl/api/memory.rs +++ b/src/gallium/frontends/rusticl/api/memory.rs @@ -3067,7 +3067,7 @@ fn enqueue_acquire_gl_objects( evs, event, false, - Box::new(|_, _| Ok(())), + Box::new(move |q, ctx| copy_cube_to_slice(q, ctx, &objs)), ) } @@ -3101,6 +3101,6 @@ fn enqueue_release_gl_objects( evs, event, false, - Box::new(move |_, _| Ok(())), + Box::new(move |q, ctx| copy_slice_to_cube(q, ctx, &objs)), ) } diff --git a/src/gallium/frontends/rusticl/core/device.rs b/src/gallium/frontends/rusticl/core/device.rs index 3b3cb306097..c1b003450b3 100644 --- a/src/gallium/frontends/rusticl/core/device.rs +++ b/src/gallium/frontends/rusticl/core/device.rs @@ -100,6 +100,16 @@ pub struct HelperContext<'a> { } impl<'a> HelperContext<'a> { + pub fn resource_copy_region( + &self, + src: &PipeResource, + dst: &PipeResource, + dst_offset: &[u32; 3], + bx: &pipe_box, + ) { + self.lock.resource_copy_region(src, dst, dst_offset, bx); + } + pub fn buffer_subdata( &self, res: &PipeResource, diff --git a/src/gallium/frontends/rusticl/core/gl.rs b/src/gallium/frontends/rusticl/core/gl.rs index 10eee45ee80..2e5534822f2 100644 --- a/src/gallium/frontends/rusticl/core/gl.rs +++ b/src/gallium/frontends/rusticl/core/gl.rs @@ -1,13 +1,26 @@ use crate::api::icd::*; +use crate::api::types::*; +use crate::core::device::*; use crate::core::format::*; +use crate::core::memory::*; +use crate::core::queue::*; +use crate::core::util::*; use libc_rust_gen::{close, dlsym}; use rusticl_opencl_gen::*; +use mesa_rust::pipe::context::*; +use mesa_rust::pipe::resource::*; +use mesa_rust::pipe::screen::*; + +use std::collections::HashMap; use std::ffi::CString; use std::mem; use std::os::raw::c_void; use std::ptr; +use std::sync::Arc; + +type CLGLMappings = Option<HashMap<Arc<PipeResource>, Arc<PipeResource>>>; pub struct XPlatManager { glx_get_proc_addr: PFNGLXGETPROCADDRESSPROC, @@ -286,6 +299,9 @@ impl GLExportManager { } _ => {} } + if is_cube_map_face(self.export_in.target) { + array_size = 6; + } Ok(GLMemProps { height: height, @@ -314,6 +330,95 @@ pub struct GLObject { pub gl_object_target: cl_GLenum, pub gl_object_type: cl_gl_object_type, pub gl_object_name: cl_GLuint, + pub shadow_map: CLGLMappings, +} + +pub fn create_shadow_slice( + cube_map: &HashMap<&'static Device, Arc<PipeResource>>, + image_format: cl_image_format, +) -> CLResult<HashMap<&'static Device, Arc<PipeResource>>> { + let mut slice = HashMap::new(); + + for (dev, imported_gl_res) in cube_map { + let width = imported_gl_res.width(); + let height = imported_gl_res.height(); + + let shadow = dev + .screen() + .resource_create_texture( + width, + height, + 1, + 1, + cl_mem_type_to_texture_target(CL_MEM_OBJECT_IMAGE2D), + image_format.to_pipe_format().unwrap(), + ResourceType::Normal, + false, + ) + .ok_or(CL_OUT_OF_HOST_MEMORY)?; + + slice.insert(*dev, Arc::new(shadow)); + } + + Ok(slice) +} + +pub fn copy_cube_to_slice( + q: &Arc<Queue>, + ctx: &PipeContext, + mem_objects: &[Arc<Mem>], +) -> CLResult<()> { + for mem in mem_objects { + let gl_obj = mem.gl_obj.as_ref().unwrap(); + if !is_cube_map_face(gl_obj.gl_object_target) { + continue; + } + let width = mem.image_desc.image_width; + let height = mem.image_desc.image_height; + + // Fill in values for doing the copy + let idx = get_array_slice_idx(gl_obj.gl_object_target); + let src_origin = CLVec::<usize>::new([0, 0, idx]); + let dst_offset: [u32; 3] = [0, 0, 0]; + let region = CLVec::<usize>::new([width, height, 1]); + let src_bx = create_pipe_box(src_origin, region, CL_MEM_OBJECT_IMAGE2D_ARRAY)?; + + let cl_res = mem.get_res_of_dev(q.device)?; + let gl_res = gl_obj.shadow_map.as_ref().unwrap().get(cl_res).unwrap(); + + ctx.resource_copy_region(gl_res.as_ref(), cl_res.as_ref(), &dst_offset, &src_bx); + } + + Ok(()) +} + +pub fn copy_slice_to_cube( + q: &Arc<Queue>, + ctx: &PipeContext, + mem_objects: &[Arc<Mem>], +) -> CLResult<()> { + for mem in mem_objects { + let gl_obj = mem.gl_obj.as_ref().unwrap(); + if !is_cube_map_face(gl_obj.gl_object_target) { + continue; + } + let width = mem.image_desc.image_width; + let height = mem.image_desc.image_height; + + // Fill in values for doing the copy + let idx = get_array_slice_idx(gl_obj.gl_object_target) as u32; + let src_origin = CLVec::<usize>::new([0, 0, 0]); + let dst_offset: [u32; 3] = [0, 0, idx]; + let region = CLVec::<usize>::new([width, height, 1]); + let src_bx = create_pipe_box(src_origin, region, CL_MEM_OBJECT_IMAGE2D_ARRAY)?; + + let cl_res = mem.get_res_of_dev(q.device)?; + let gl_res = gl_obj.shadow_map.as_ref().unwrap().get(cl_res).unwrap(); + + ctx.resource_copy_region(cl_res.as_ref(), gl_res.as_ref(), &dst_offset, &src_bx); + } + + Ok(()) } pub fn interop_to_cl_error(error: i32) -> CLError { @@ -385,3 +490,27 @@ pub fn is_valid_gl_texture_2d(target: u32) -> bool { | GL_TEXTURE_CUBE_MAP_POSITIVE_Z ) } + +pub fn get_array_slice_idx(target: u32) -> usize { + match target { + 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 => (target - GL_TEXTURE_CUBE_MAP_POSITIVE_X) as usize, + _ => 0, + } +} + +pub fn is_cube_map_face(target: u32) -> bool { + matches!( + target, + 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 7ab9cb870de..60f5c067780 100644 --- a/src/gallium/frontends/rusticl/core/memory.rs +++ b/src/gallium/frontends/rusticl/core/memory.rs @@ -453,7 +453,7 @@ impl Mem { (image_format, image_format.to_pipe_format().unwrap()) }; - let texture = context.import_gl_buffer( + let imported_gl_tex = context.import_gl_buffer( export_out.dmabuf_fd as u32, export_out.modifier, mem_type, @@ -461,10 +461,30 @@ impl Mem { gl_mem_props.clone(), )?; + // Cube maps faces are not linear in memory, so copy all contents + // of desired face into a 2D image and copy it back after gl release. + let (shadow_map, texture) = if is_cube_map_face(export_in.target) { + let shadow = create_shadow_slice(&imported_gl_tex, image_format)?; + + let mut res_map = HashMap::new(); + shadow + .iter() + .map(|(k, v)| { + let gl_res = imported_gl_tex.get(k).unwrap().clone(); + res_map.insert(v.clone(), gl_res); + }) + .for_each(drop); + + (Some(res_map), shadow) + } else { + (None, imported_gl_tex) + }; + 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, + shadow_map: shadow_map, }; let desc = cl_image_desc { diff --git a/src/gallium/frontends/rusticl/mesa/pipe/resource.rs b/src/gallium/frontends/rusticl/mesa/pipe/resource.rs index 3b8075610ca..b7c2ae4a2a0 100644 --- a/src/gallium/frontends/rusticl/mesa/pipe/resource.rs +++ b/src/gallium/frontends/rusticl/mesa/pipe/resource.rs @@ -2,6 +2,7 @@ use mesa_rust_gen::*; use std::ptr; +#[derive(PartialEq, Eq, Hash)] pub struct PipeResource { pipe: *mut pipe_resource, pub is_user: bool,