mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-03-11 09:10:32 +01:00
rusticl: Add functions to create CL ctxs from GL, and also to query them
Reviewed-by: Karol Herbst <kherbst@redhat.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21305>
This commit is contained in:
parent
425d7acd4a
commit
57dfc013a6
6 changed files with 214 additions and 5 deletions
|
|
@ -2,7 +2,8 @@ use crate::api::icd::*;
|
|||
use crate::api::types::*;
|
||||
use crate::api::util::*;
|
||||
use crate::core::context::*;
|
||||
use crate::core::device::get_devs_for_type;
|
||||
use crate::core::device::{get_dev_for_uuid, get_devs_for_type, get_devs_with_gl_interop};
|
||||
use crate::core::gl::*;
|
||||
use crate::core::platform::*;
|
||||
|
||||
use mesa_rust_util::properties::Properties;
|
||||
|
|
@ -11,8 +12,10 @@ use rusticl_proc_macros::cl_entrypoint;
|
|||
use rusticl_proc_macros::cl_info_entrypoint;
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::ffi::c_void;
|
||||
use std::iter::FromIterator;
|
||||
use std::mem::MaybeUninit;
|
||||
use std::ptr;
|
||||
use std::slice;
|
||||
|
||||
#[cl_info_entrypoint(cl_get_context_info)]
|
||||
|
|
@ -35,6 +38,75 @@ impl CLInfo<cl_context_info> for cl_context {
|
|||
}
|
||||
}
|
||||
|
||||
impl CLInfo<cl_gl_context_info> for GLCtxManager {
|
||||
fn query(&self, q: cl_gl_context_info, _: &[u8]) -> CLResult<Vec<MaybeUninit<u8>>> {
|
||||
let info = self.interop_dev_info;
|
||||
|
||||
Ok(match q {
|
||||
CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR => {
|
||||
let ptr = match get_dev_for_uuid(info.device_uuid) {
|
||||
Some(dev) => dev,
|
||||
None => ptr::null(),
|
||||
};
|
||||
cl_prop::<cl_device_id>(cl_device_id::from_ptr(ptr))
|
||||
}
|
||||
CL_DEVICES_FOR_GL_CONTEXT_KHR => {
|
||||
let devs = get_devs_with_gl_interop()
|
||||
.iter()
|
||||
.map(|&d| cl_device_id::from_ptr(d))
|
||||
.collect();
|
||||
cl_prop::<&Vec<cl_device_id>>(&devs)
|
||||
}
|
||||
_ => return Err(CL_INVALID_VALUE),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cl_entrypoint]
|
||||
pub fn get_gl_context_info_khr(
|
||||
properties: *const cl_context_properties,
|
||||
param_name: cl_gl_context_info,
|
||||
param_value_size: usize,
|
||||
param_value: *mut ::std::os::raw::c_void,
|
||||
param_value_size_ret: *mut usize,
|
||||
) -> CLResult<()> {
|
||||
let mut egl_display: EGLDisplay = ptr::null_mut();
|
||||
let mut glx_display: *mut _XDisplay = ptr::null_mut();
|
||||
let mut gl_context: *mut c_void = ptr::null_mut();
|
||||
|
||||
// CL_INVALID_PROPERTY [...] if the same property name is specified more than once.
|
||||
let props = Properties::from_ptr(properties).ok_or(CL_INVALID_PROPERTY)?;
|
||||
for p in &props.props {
|
||||
match p.0 as u32 {
|
||||
// CL_INVALID_PLATFORM [...] if platform value specified in properties is not a valid platform.
|
||||
CL_CONTEXT_PLATFORM => {
|
||||
(p.1 as cl_platform_id).get_ref()?;
|
||||
}
|
||||
CL_EGL_DISPLAY_KHR => {
|
||||
egl_display = p.1 as *mut _;
|
||||
}
|
||||
CL_GL_CONTEXT_KHR => {
|
||||
gl_context = p.1 as *mut _;
|
||||
}
|
||||
CL_GLX_DISPLAY_KHR => {
|
||||
glx_display = p.1 as *mut _;
|
||||
}
|
||||
// CL_INVALID_PROPERTY if context property name in properties is not a supported property name
|
||||
_ => return Err(CL_INVALID_PROPERTY),
|
||||
}
|
||||
}
|
||||
|
||||
let gl_ctx_manager = GLCtxManager::new(gl_context, glx_display, egl_display)?;
|
||||
gl_ctx_manager
|
||||
.ok_or(CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR)?
|
||||
.get_info(
|
||||
param_name,
|
||||
param_value_size,
|
||||
param_value,
|
||||
param_value_size_ret,
|
||||
)
|
||||
}
|
||||
|
||||
#[cl_entrypoint]
|
||||
fn create_context(
|
||||
properties: *const cl_context_properties,
|
||||
|
|
@ -58,6 +130,10 @@ fn create_context(
|
|||
return Err(CL_INVALID_VALUE);
|
||||
}
|
||||
|
||||
let mut egl_display: EGLDisplay = ptr::null_mut();
|
||||
let mut glx_display: *mut _XDisplay = ptr::null_mut();
|
||||
let mut gl_context: *mut c_void = ptr::null_mut();
|
||||
|
||||
// CL_INVALID_PROPERTY [...] if the same property name is specified more than once.
|
||||
let props = Properties::from_ptr(properties).ok_or(CL_INVALID_PROPERTY)?;
|
||||
for p in &props.props {
|
||||
|
|
@ -69,17 +145,32 @@ fn create_context(
|
|||
CL_CONTEXT_INTEROP_USER_SYNC => {
|
||||
check_cl_bool(p.1).ok_or(CL_INVALID_PROPERTY)?;
|
||||
}
|
||||
CL_EGL_DISPLAY_KHR => {
|
||||
egl_display = p.1 as *mut _;
|
||||
}
|
||||
CL_GL_CONTEXT_KHR => {
|
||||
gl_context = p.1 as *mut _;
|
||||
}
|
||||
CL_GLX_DISPLAY_KHR => {
|
||||
glx_display = p.1 as *mut _;
|
||||
}
|
||||
// CL_INVALID_PROPERTY if context property name in properties is not a supported property name
|
||||
_ => return Err(CL_INVALID_PROPERTY),
|
||||
}
|
||||
}
|
||||
|
||||
let gl_ctx_manager = GLCtxManager::new(gl_context, glx_display, egl_display)?;
|
||||
|
||||
// Duplicate devices specified in devices are ignored.
|
||||
let set: HashSet<_> =
|
||||
HashSet::from_iter(unsafe { slice::from_raw_parts(devices, num_devices as usize) }.iter());
|
||||
let devs: Result<_, _> = set.into_iter().map(cl_device_id::get_ref).collect();
|
||||
|
||||
Ok(cl_context::from_arc(Context::new(devs?, props)))
|
||||
Ok(cl_context::from_arc(Context::new(
|
||||
devs?,
|
||||
props,
|
||||
gl_ctx_manager,
|
||||
)))
|
||||
}
|
||||
|
||||
#[cl_entrypoint]
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ pub static DISPATCH: cl_icd_dispatch = cl_icd_dispatch {
|
|||
clGetGLTextureInfo: None,
|
||||
clEnqueueAcquireGLObjects: None,
|
||||
clEnqueueReleaseGLObjects: None,
|
||||
clGetGLContextInfoKHR: None,
|
||||
clGetGLContextInfoKHR: Some(cl_get_gl_context_info_khr),
|
||||
clGetDeviceIDsFromD3D10KHR: ptr::null_mut(),
|
||||
clCreateFromD3D10BufferKHR: ptr::null_mut(),
|
||||
clCreateFromD3D10Texture2DKHR: ptr::null_mut(),
|
||||
|
|
@ -413,6 +413,9 @@ extern "C" fn cl_get_extension_function_address(
|
|||
// cl_khr_il_program
|
||||
"clCreateProgramWithILKHR" => cl_create_program_with_il as *mut ::std::ffi::c_void,
|
||||
|
||||
// cl_khr_gl_sharing
|
||||
"clGetGLContextInfoKHR" => cl_get_gl_context_info_khr as *mut ::std::ffi::c_void,
|
||||
|
||||
// cl_arm_shared_virtual_memory
|
||||
"clEnqueueSVMFreeARM" => cl_enqueue_svm_free_arm as *mut ::std::ffi::c_void,
|
||||
"clEnqueueSVMMapARM" => cl_enqueue_svm_map_arm as *mut ::std::ffi::c_void,
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ use crate::api::icd::*;
|
|||
use crate::api::types::DeleteContextCB;
|
||||
use crate::core::device::*;
|
||||
use crate::core::format::*;
|
||||
use crate::core::gl::*;
|
||||
use crate::core::memory::*;
|
||||
use crate::core::util::*;
|
||||
use crate::impl_cl_type_trait;
|
||||
|
|
@ -26,6 +27,7 @@ pub struct Context {
|
|||
pub properties: Properties<cl_context_properties>,
|
||||
pub dtors: Mutex<Vec<DeleteContextCB>>,
|
||||
pub svm_ptrs: Mutex<BTreeMap<*const c_void, Layout>>,
|
||||
pub gl_ctx_manager: Option<GLCtxManager>,
|
||||
}
|
||||
|
||||
impl_cl_type_trait!(cl_context, Context, CL_INVALID_CONTEXT);
|
||||
|
|
@ -34,6 +36,7 @@ impl Context {
|
|||
pub fn new(
|
||||
devs: Vec<&'static Device>,
|
||||
properties: Properties<cl_context_properties>,
|
||||
gl_ctx_manager: Option<GLCtxManager>,
|
||||
) -> Arc<Context> {
|
||||
Arc::new(Self {
|
||||
base: CLObjectBase::new(),
|
||||
|
|
@ -41,6 +44,7 @@ impl Context {
|
|||
properties: properties,
|
||||
dtors: Mutex::new(Vec::new()),
|
||||
svm_ptrs: Mutex::new(BTreeMap::new()),
|
||||
gl_ctx_manager: gl_ctx_manager,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ use std::collections::HashMap;
|
|||
use std::convert::TryInto;
|
||||
use std::env;
|
||||
use std::ffi::CString;
|
||||
use std::mem::transmute;
|
||||
use std::os::raw::*;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
|
|
@ -1003,7 +1004,7 @@ impl Device {
|
|||
}
|
||||
}
|
||||
|
||||
fn devs() -> &'static Vec<Arc<Device>> {
|
||||
pub fn devs() -> &'static Vec<Arc<Device>> {
|
||||
&Platform::get().devs
|
||||
}
|
||||
|
||||
|
|
@ -1014,3 +1015,21 @@ pub fn get_devs_for_type(device_type: cl_device_type) -> Vec<&'static Device> {
|
|||
.map(Arc::as_ref)
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn get_dev_for_uuid(uuid: [c_char; UUID_SIZE]) -> Option<&'static Device> {
|
||||
devs()
|
||||
.iter()
|
||||
.find(|d| {
|
||||
let uuid: [c_uchar; UUID_SIZE] = unsafe { transmute(uuid) };
|
||||
uuid == d.screen().device_uuid().unwrap()
|
||||
})
|
||||
.map(Arc::as_ref)
|
||||
}
|
||||
|
||||
pub fn get_devs_with_gl_interop() -> Vec<&'static Device> {
|
||||
devs()
|
||||
.iter()
|
||||
.filter(|d| d.is_gl_sharing_supported())
|
||||
.map(Arc::as_ref)
|
||||
.collect()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ use rusticl_opencl_gen::*;
|
|||
|
||||
use std::ffi::CString;
|
||||
use std::mem;
|
||||
use std::os::raw::c_void;
|
||||
use std::ptr;
|
||||
|
||||
pub struct XPlatManager {
|
||||
|
|
@ -89,3 +90,94 @@ impl XPlatManager {
|
|||
self.get_func::<PFNMESAGLINTEROPGLXFLUSHOBJECTSPROC>("glXGLInteropFlushObjectsMESA")
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::upper_case_acronyms)]
|
||||
#[derive(PartialEq, Eq)]
|
||||
enum GLCtx {
|
||||
EGL(EGLDisplay, EGLContext),
|
||||
GLX(*mut _XDisplay, *mut __GLXcontextRec),
|
||||
}
|
||||
|
||||
pub struct GLCtxManager {
|
||||
pub interop_dev_info: mesa_glinterop_device_info,
|
||||
pub xplat_manager: XPlatManager,
|
||||
gl_ctx: GLCtx,
|
||||
}
|
||||
|
||||
impl GLCtxManager {
|
||||
pub fn new(
|
||||
gl_context: *mut c_void,
|
||||
glx_display: *mut _XDisplay,
|
||||
egl_display: EGLDisplay,
|
||||
) -> CLResult<Option<Self>> {
|
||||
let mut info = mesa_glinterop_device_info {
|
||||
version: 3,
|
||||
..Default::default()
|
||||
};
|
||||
let xplat_manager = XPlatManager::new();
|
||||
|
||||
// More than one of the attributes CL_CGL_SHAREGROUP_KHR, CL_EGL_DISPLAY_KHR,
|
||||
// CL_GLX_DISPLAY_KHR, and CL_WGL_HDC_KHR is set to a non-default value.
|
||||
if !egl_display.is_null() && !glx_display.is_null() {
|
||||
return Err(CL_INVALID_OPERATION);
|
||||
}
|
||||
|
||||
if gl_context.is_null() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
if !egl_display.is_null() {
|
||||
let egl_query_device_info_func = xplat_manager
|
||||
.MesaGLInteropEGLQueryDeviceInfo()?
|
||||
.ok_or(CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR)?;
|
||||
|
||||
let err = unsafe {
|
||||
egl_query_device_info_func(egl_display.cast(), gl_context.cast(), &mut info)
|
||||
};
|
||||
|
||||
if err != MESA_GLINTEROP_SUCCESS as i32 {
|
||||
return Err(interop_to_cl_error(err));
|
||||
}
|
||||
|
||||
Ok(Some(GLCtxManager {
|
||||
gl_ctx: GLCtx::EGL(egl_display.cast(), gl_context),
|
||||
interop_dev_info: info,
|
||||
xplat_manager: xplat_manager,
|
||||
}))
|
||||
} else if !glx_display.is_null() {
|
||||
let glx_query_device_info_func = xplat_manager
|
||||
.MesaGLInteropGLXQueryDeviceInfo()?
|
||||
.ok_or(CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR)?;
|
||||
|
||||
let err = unsafe {
|
||||
glx_query_device_info_func(glx_display.cast(), gl_context.cast(), &mut info)
|
||||
};
|
||||
|
||||
if err != MESA_GLINTEROP_SUCCESS as i32 {
|
||||
return Err(interop_to_cl_error(err));
|
||||
}
|
||||
|
||||
Ok(Some(GLCtxManager {
|
||||
gl_ctx: GLCtx::GLX(glx_display.cast(), gl_context.cast()),
|
||||
interop_dev_info: info,
|
||||
xplat_manager: xplat_manager,
|
||||
}))
|
||||
} else {
|
||||
Err(CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn interop_to_cl_error(error: i32) -> CLError {
|
||||
match error.try_into().unwrap() {
|
||||
MESA_GLINTEROP_OUT_OF_RESOURCES => CL_OUT_OF_RESOURCES,
|
||||
MESA_GLINTEROP_OUT_OF_HOST_MEMORY => CL_OUT_OF_HOST_MEMORY,
|
||||
MESA_GLINTEROP_INVALID_OPERATION => CL_INVALID_OPERATION,
|
||||
MESA_GLINTEROP_INVALID_CONTEXT | MESA_GLINTEROP_INVALID_DISPLAY => {
|
||||
CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR
|
||||
}
|
||||
MESA_GLINTEROP_INVALID_TARGET | MESA_GLINTEROP_INVALID_OBJECT => CL_INVALID_GL_OBJECT,
|
||||
MESA_GLINTEROP_INVALID_MIP_LEVEL => CL_INVALID_MIP_LEVEL,
|
||||
_ => CL_OUT_OF_HOST_MEMORY,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ pub struct PipeScreen {
|
|||
screen: *mut pipe_screen,
|
||||
}
|
||||
|
||||
const UUID_SIZE: usize = PIPE_UUID_SIZE as usize;
|
||||
pub const UUID_SIZE: usize = PIPE_UUID_SIZE as usize;
|
||||
const LUID_SIZE: usize = PIPE_LUID_SIZE as usize;
|
||||
|
||||
// until we have a better solution
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue