#![allow(unused_unsafe)]
#![allow(non_camel_case_types)]
#![allow(clippy::not_unsafe_ptr_arg_deref)]
pub use opencl_sys::{
CL_CONTEXT_DEVICES, CL_CONTEXT_INTEROP_USER_SYNC, CL_CONTEXT_NUM_DEVICES, CL_CONTEXT_PLATFORM,
CL_CONTEXT_PROPERTIES, CL_CONTEXT_REFERENCE_COUNT, CL_INVALID_VALUE, CL_SUCCESS, cl_context,
cl_context_info, cl_context_properties, cl_device_id, cl_device_type, cl_int, cl_uint,
};
use super::info_type::InfoType;
use super::{api_info_size, api_info_value, api_info_vector};
use libc::{c_char, c_void, intptr_t, size_t};
use std::mem;
use std::ptr;
#[allow(unused_unsafe)]
#[allow(clippy::cast_possible_truncation)]
#[inline]
pub fn create_context(
devices: &[cl_device_id],
properties: *const cl_context_properties,
pfn_notify: Option<unsafe extern "C" fn(*const c_char, *const c_void, size_t, *mut c_void)>,
user_data: *mut c_void,
) -> Result<cl_context, cl_int> {
let mut status: cl_int = CL_INVALID_VALUE;
let context = unsafe {
cl_call!(clCreateContext(
properties,
devices.len() as cl_uint,
devices.as_ptr(),
pfn_notify,
user_data,
&raw mut status,
))
};
if CL_SUCCESS == status {
Ok(context)
} else {
Err(status)
}
}
#[inline]
pub fn create_context_from_type(
device_type: cl_device_type,
properties: *const cl_context_properties,
pfn_notify: Option<unsafe extern "C" fn(*const c_char, *const c_void, size_t, *mut c_void)>,
user_data: *mut c_void,
) -> Result<cl_context, cl_int> {
let mut status: cl_int = CL_INVALID_VALUE;
let context = unsafe {
cl_call!(clCreateContextFromType(
properties,
device_type,
pfn_notify,
user_data,
&raw mut status
))
};
if CL_SUCCESS == status {
Ok(context)
} else {
Err(status)
}
}
#[inline]
pub unsafe fn retain_context(context: cl_context) -> Result<(), cl_int> {
let status: cl_int = cl_call!(clRetainContext(context));
if CL_SUCCESS == status {
Ok(())
} else {
Err(status)
}
}
#[inline]
pub unsafe fn release_context(context: cl_context) -> Result<(), cl_int> {
let status: cl_int = cl_call!(clReleaseContext(context));
if CL_SUCCESS == status {
Ok(())
} else {
Err(status)
}
}
pub fn get_context_data(
context: cl_context,
param_name: cl_context_info,
) -> Result<Vec<u8>, cl_int> {
api_info_size!(get_size, clGetContextInfo);
let size = get_size(context, param_name)?;
api_info_vector!(get_vector, u8, clGetContextInfo);
get_vector(context, param_name, size)
}
pub fn get_context_info(
context: cl_context,
param_name: cl_context_info,
) -> Result<InfoType, cl_int> {
api_info_size!(get_size, clGetContextInfo);
match param_name {
CL_CONTEXT_REFERENCE_COUNT | CL_CONTEXT_NUM_DEVICES => {
api_info_value!(get_value, cl_uint, clGetContextInfo);
Ok(InfoType::Uint(get_value(context, param_name)?))
}
CL_CONTEXT_DEVICES | CL_CONTEXT_PROPERTIES => {
api_info_vector!(get_vec, intptr_t, clGetContextInfo);
let size = get_size(context, param_name)?;
Ok(InfoType::VecIntPtr(get_vec(context, param_name, size)?))
}
_ => Ok(InfoType::VecUchar(get_context_data(context, param_name)?)),
}
}
#[cfg(any(feature = "CL_VERSION_3_0", feature = "dynamic"))]
#[inline]
pub fn set_context_destructor_callback(
context: cl_context,
pfn_notify: Option<unsafe extern "C" fn(cl_context, *mut c_void)>,
user_data: *mut c_void,
) -> Result<(), cl_int> {
let status: cl_int = unsafe {
cl_call!(clSetContextDestructorCallback(
context, pfn_notify, user_data
))
};
if CL_SUCCESS == status {
Ok(())
} else {
Err(status)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::device::{CL_DEVICE_TYPE_GPU, get_device_ids};
use crate::platform::get_platform_ids;
#[test]
fn test_context() {
let platform_ids = get_platform_ids().unwrap();
let platform_id = platform_ids[0];
let device_ids = get_device_ids(platform_id, CL_DEVICE_TYPE_GPU).unwrap();
assert!(0 < device_ids.len());
let context = create_context(&device_ids, ptr::null(), None, ptr::null_mut());
let context = context.unwrap();
let value = get_context_info(context, CL_CONTEXT_REFERENCE_COUNT).unwrap();
let value = cl_uint::from(value);
println!("CL_CONTEXT_REFERENCE_COUNT: {}", value);
assert!(0 < value);
let value = get_context_info(context, CL_CONTEXT_DEVICES).unwrap();
let value = Vec::<intptr_t>::from(value);
println!("CL_CONTEXT_DEVICES: {}", value.len());
println!("CL_CONTEXT_DEVICES: {:?}", value);
assert!(0 < value.len());
let value = get_context_info(context, CL_CONTEXT_PROPERTIES).unwrap();
let value = Vec::<intptr_t>::from(value);
println!("CL_CONTEXT_PROPERTIES: {}", value.len());
println!("CL_CONTEXT_PROPERTIES: {:?}", value);
let value = get_context_info(context, CL_CONTEXT_NUM_DEVICES).unwrap();
let value = cl_uint::from(value);
println!("CL_CONTEXT_NUM_DEVICES: {}", value);
assert!(0 < value);
unsafe { release_context(context).unwrap() };
}
}