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,

Reply via email to