rusticl: Add support for cube maps

Reviewed-by: Karol Herbst <kherbst@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21305>
This commit is contained in:
Antonio Gomes 2023-04-21 21:41:25 -03:00 committed by Marge Bot
parent 2645003bdc
commit 1c3dde7ba6
5 changed files with 163 additions and 3 deletions

View file

@ -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)),
)
}

View file

@ -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,

View file

@ -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
)
}

View file

@ -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 {

View file

@ -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,