-
Notifications
You must be signed in to change notification settings - Fork 59
/
Copy pathlib.rs
153 lines (138 loc) · 5.21 KB
/
lib.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
//! af-opencl-interop package is to used only when the application intends to mix
//! arrayfire code with raw OpenCL code.
//!
//! Functions from this crate return OpenCL C API opaque pointers typedefs
//!
//! - [cl_device_id](https://docs.rs/cl-sys/0.4.2/cl_sys/type.cl_device_id.html)
//! - [cl_context](https://docs.rs/cl-sys/0.4.2/cl_sys/type.cl_context.html)
//! - [cl_command_queue](https://docs.rs/cl-sys/0.4.2/cl_sys/type.cl_command_queue.html)
use arrayfire::{handle_error_general, AfError};
use cl_sys::{
cl_command_queue, cl_context, cl_device_id, CL_DEVICE_TYPE_ACCELERATOR, CL_DEVICE_TYPE_ALL,
CL_DEVICE_TYPE_CPU, CL_DEVICE_TYPE_DEFAULT, CL_DEVICE_TYPE_GPU,
};
use libc::c_int;
use std::mem;
/// OpenCL Vendor Platform
#[repr(i32)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum VendorPlatform {
AMD = 0,
APPLE = 1,
INTEL = 2,
NVIDIA = 3,
BEIGNET = 4,
POCL = 5,
UNKNOWN = -1,
}
/// OpenCL Device Type
#[repr(u64)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum DeviceType {
DEFAULT = CL_DEVICE_TYPE_DEFAULT,
CPU = CL_DEVICE_TYPE_CPU,
GPU = CL_DEVICE_TYPE_GPU,
ACCEL = CL_DEVICE_TYPE_ACCELERATOR,
ALL = CL_DEVICE_TYPE_ALL,
}
extern "C" {
fn afcl_get_context(ctx: *mut cl_context, retain: bool) -> c_int;
fn afcl_get_queue(queue: *mut cl_command_queue, retain: bool) -> c_int;
fn afcl_get_device_id(out: *mut cl_device_id) -> c_int;
fn afcl_set_device_id(id: cl_device_id) -> c_int;
fn afcl_add_device_context(
dev_id: cl_device_id,
ctx: cl_context,
queue: cl_command_queue,
) -> c_int;
fn afcl_set_device_context(dev_id: cl_device_id, ctx: cl_context) -> c_int;
fn afcl_delete_device_context(dev_id: cl_device_id, ctx: cl_context) -> c_int;
fn afcl_get_device_type(dtype: *mut c_int) -> c_int;
fn afcl_get_platform(ptype: *mut c_int) -> c_int;
}
/// Get the handle to active ArrayFire OpenCL context
pub fn get_context(retain: bool) -> cl_context {
unsafe {
let mut out: cl_context = std::ptr::null_mut();
let err_val = afcl_get_context(&mut out as *mut cl_context, retain);
handle_error_general(AfError::from(err_val));
out
}
}
/// Get the handle to active ArrayFire OpenCL command queue
pub fn get_queue(retain: bool) -> cl_command_queue {
unsafe {
let mut out: cl_command_queue = std::ptr::null_mut();
let err_val = afcl_get_queue(&mut out as *mut cl_command_queue, retain);
handle_error_general(AfError::from(err_val));
out
}
}
/// Get the handle to active ArrayFire OpenCL device
pub fn get_device_id() -> cl_device_id {
unsafe {
let mut out: cl_device_id = std::ptr::null_mut();
let err_val = afcl_get_device_id(&mut out as *mut cl_device_id);
handle_error_general(AfError::from(err_val));
out
}
}
/// Set the cl_device_id as the active ArrayFire OpenCL device
///
/// # Safety
///
/// This function is to be only called if user intends to set a particular
/// opencl device explicitly. This is low level function and it's for only
/// advanced users.
pub unsafe fn set_device_id(dev_id: cl_device_id) {
let err_val = afcl_set_device_id(dev_id);
handle_error_general(AfError::from(err_val));
}
/// Push user provided device, context and queue tuple to ArrayFire device mamanger
///
/// # Safety
///
/// This function is to be only called if user intends to add a opencl device context
/// explicitly. This is low level function and it's for only advanced users.
pub unsafe fn add_device_context(dev_id: cl_device_id, ctx: cl_context, queue: cl_command_queue) {
let err_val = afcl_add_device_context(dev_id, ctx, queue);
handle_error_general(AfError::from(err_val));
}
/// Set the device identified by device & context pair as the active device for ArrayFire
///
/// # Safety
///
/// This function is to be only called if user intends mark a given opencl device
/// as current device. It is for advanced users only.
pub unsafe fn set_device_context(dev_id: cl_device_id, ctx: cl_context) {
let err_val = afcl_set_device_context(dev_id, ctx);
handle_error_general(AfError::from(err_val));
}
/// Remove the user provided device, context pair from ArrayFire device mamanger
///
/// # Safety
///
/// This function is to be only called if user intends to delete a prior added
/// opencl device context. Using this for devices not added by user explicitly
/// can result in undefined behavior.
pub unsafe fn delete_device_context(dev_id: cl_device_id, ctx: cl_context) {
let err_val = afcl_delete_device_context(dev_id, ctx);
handle_error_general(AfError::from(err_val));
}
///// Fetch Active ArrayFire device's type i.e. CPU/GPU/Accelerator etc.
pub fn get_device_type() -> DeviceType {
let mut out: i32 = 0;
let err_val = unsafe { afcl_get_device_type(&mut out as *mut c_int) };
handle_error_general(AfError::from(err_val));
match out {
-1 => unsafe { mem::transmute(out as u64) },
_ => DeviceType::ALL,
}
}
/// Fetch Active ArrayFire device's vendor platform
pub fn get_platform() -> VendorPlatform {
let mut out: i32 = 0;
let err_val = unsafe { afcl_get_platform(&mut out as *mut c_int) };
handle_error_general(AfError::from(err_val));
unsafe { mem::transmute(out) }
}