mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-25 04:20:08 +01:00
rusticl: Create CL mem objects from GL
Reviewed-by: Karol Herbst <kherbst@redhat.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21305>
This commit is contained in:
parent
0bafe8be2c
commit
2645003bdc
7 changed files with 585 additions and 10 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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(())),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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) }
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue