use {BoxContext, Build, Context, Error, ErrorKind, ExtensionPackage, Framework};
use {Hardware, HardwareKind, Result};
use std::marker::Unsize;
use super::{OpenCLContext, OpenCLDevice};
use super::super::{foreign, high};
use utility::{TryDefault, Uninitialized};
const OPEN_CL: &'static str = "OpenCL";
#[derive(Debug)]
pub struct OpenCL {
cache: Vec<high::Device>,
selection: Vec<Hardware>,
pub available_hardware: Vec<Hardware>,
}
impl OpenCL {
pub fn new() -> Result<OpenCL> {
OpenCL::try_default()
}
}
impl Framework for OpenCL {
const FRAMEWORK_NAME: &'static str = OPEN_CL;
fn selection(&self) -> &[Hardware] {
&self.selection
}
fn available_hardware(&self) -> Vec<Hardware> {
self.available_hardware.clone()
}
}
impl<X> BoxContext<X> for OpenCL
where X: ExtensionPackage + Build<OpenCLContext<Uninitialized>>,
OpenCLContext<X>: Unsize<X::Extension>
{
fn enclose(&mut self, hw_selection: Vec<Hardware>) -> Result<Box<Context<Package = X>>> {
self.selection = hw_selection.clone();
let indices: Vec<usize> = hw_selection.iter().map(|hardware| hardware.id).collect();
let devices: Vec<high::Device> = self.cache
.iter()
.enumerate()
.filter(|&(idx, _)| indices.contains(&idx))
.map(|(_, device)| device.clone())
.collect();
let hl_context = high::Context::new(&devices)?;
let mut selection = vec![];
for raw_device in devices.into_iter() {
let queue = high::Queue::new(&hl_context, &raw_device, foreign::CL_QUEUE_PROFILING_ENABLE)?;
selection.push(OpenCLDevice {
device: raw_device,
context: hl_context.clone(),
queue,
});
}
let mut context: OpenCLContext<Uninitialized> = OpenCLContext {
context: hl_context,
package: (),
selection: selection,
active: 0,
};
let package = X::build(&mut context)?;
Ok(Box::new(OpenCLContext {
context: context.context,
package: package,
selection: context.selection,
active: context.active,
}))
}
}
impl TryDefault for OpenCL {
type Err = Error;
fn try_default() -> Result<OpenCL> {
let mut cache = vec![];
let available_hardware = {
high::platforms()?.remove(0).devices()?.into_iter()
.enumerate()
.map(|(index, dev_handle)| {
let hardware = Hardware {
id: index,
framework: OPEN_CL,
kind: match dev_handle.type_().unwrap() {
foreign::CL_DEVICE_TYPE_CPU => HardwareKind::CPU,
foreign::CL_DEVICE_TYPE_GPU => HardwareKind::GPU,
foreign::CL_DEVICE_TYPE_ACCELERATOR => HardwareKind::Accelerator,
_ => HardwareKind::Other,
},
name: dev_handle.name().unwrap(),
compute_units: dev_handle.max_compute_units().unwrap() as usize,
};
cache.push(dev_handle);
hardware
})
.collect()
};
Ok(OpenCL { cache, selection: vec![], available_hardware })
}
}
impl From<high::Error> for Error {
fn from(e: high::Error) -> Error {
Error::new(ErrorKind::Framework { name: OPEN_CL }, e)
}
}