#![allow(non_camel_case_types)]
#![allow(clippy::not_unsafe_ptr_arg_deref)]
pub use opencl_sys::{
cl_context, cl_context_info, cl_context_properties, cl_device_id, cl_device_type, cl_int,
cl_uint, 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,
};
use opencl_sys::{
clCreateContext, clCreateContextFromType, clGetContextInfo, clReleaseContext, clRetainContext,
};
#[cfg(feature = "CL_VERSION_3_0")]
use opencl_sys::clSetContextDestructorCallback;
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;
#[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 {
clCreateContext(
properties,
devices.len() as cl_uint,
devices.as_ptr(),
pfn_notify,
user_data,
&mut status,
)
};
if CL_SUCCESS != status {
Err(status)
} else {
Ok(context)
}
}
#[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 {
clCreateContextFromType(properties, device_type, pfn_notify, user_data, &mut status)
};
if CL_SUCCESS != status {
Err(status)
} else {
Ok(context)
}
}
#[inline]
pub unsafe fn retain_context(context: cl_context) -> Result<(), cl_int> {
let status: cl_int = clRetainContext(context);
if CL_SUCCESS != status {
Err(status)
} else {
Ok(())
}
}
#[inline]
pub unsafe fn release_context(context: cl_context) -> Result<(), cl_int> {
let status: cl_int = clReleaseContext(context);
if CL_SUCCESS != status {
Err(status)
} else {
Ok(())
}
}
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(feature = "CL_VERSION_3_0")]
#[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 { clSetContextDestructorCallback(context, pfn_notify, user_data) };
if CL_SUCCESS != status {
Err(status)
} else {
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::device::{get_device_ids, CL_DEVICE_TYPE_GPU};
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();
}
}
}