open-cl-low-level 0.2.1

OpenCL low-level bindings
Documentation
use crate::{
    list_devices_by_type, list_platforms, ClContext, ClDeviceID, ClPlatformID, DeviceType, Error,
    Output,
};

#[derive(Debug, Fail, PartialEq, Eq, Clone)]
pub enum ContextBuilderError {
    #[fail(display = "For context building devices and device type cannot both be specified")]
    CannotSpecifyDevicesAndDeviceType,

    #[fail(display = "For context building devices and platforms cannot both be specified")]
    CannotSpecifyDevicesAndPlatforms,
}

const DEVICES_AND_DEVICE_TYPE_ERROR: Error =
    Error::ContextBuilderError(ContextBuilderError::CannotSpecifyDevicesAndDeviceType);
const DEVICES_AND_PLATFORMS_ERROR: Error =
    Error::ContextBuilderError(ContextBuilderError::CannotSpecifyDevicesAndPlatforms);

pub struct ClContextBuilder<'a> {
    pub platforms: Option<&'a [ClPlatformID]>,
    pub device_type: Option<DeviceType>,
    pub devices: Option<&'a [ClDeviceID]>,
}

impl<'a> ClContextBuilder<'a> {
    pub fn new() -> ClContextBuilder<'a> {
        ClContextBuilder {
            platforms: None,
            device_type: None,
            devices: None,
        }
    }

    pub fn with_platforms(mut self, platforms: &'a [ClPlatformID]) -> ClContextBuilder<'a> {
        self.platforms = Some(platforms);
        self
    }

    pub fn with_device_type(mut self, device_type: DeviceType) -> ClContextBuilder<'a> {
        self.device_type = Some(device_type);
        self
    }

    pub fn with_devices(mut self, devices: &'a [ClDeviceID]) -> ClContextBuilder<'a> {
        self.devices = Some(devices);
        self
    }

    pub unsafe fn build(self) -> Output<BuiltClContext> {
        use ClContextBuilder as B;
        match self {
            B {
                device_type: Some(device_type),
                devices: None,
                platforms: None,
            } => ClContextBuilder::build_from_device_type(device_type),
            B {
                devices: Some(devices),
                device_type: None,
                platforms: None,
            } => ClContextBuilder::build_from_devices(devices),
            B {
                platforms: Some(platforms),
                device_type: None,
                devices: None,
            } => ClContextBuilder::build_from_platforms(platforms),
            B {
                platforms: Some(platforms),
                device_type: Some(device_type),
                devices: None,
            } => ClContextBuilder::build_from_platforms_with_device_type(platforms, device_type),
            B {
                platforms: None,
                device_type: None,
                devices: None,
            } => ClContextBuilder::build_with_defaults(),
            B {
                device_type: Some(_),
                devices: Some(_),
                ..
            } => Err(DEVICES_AND_DEVICE_TYPE_ERROR),
            B {
                devices: Some(_),
                platforms: Some(_),
                ..
            } => Err(DEVICES_AND_PLATFORMS_ERROR),
        }
    }

    pub unsafe fn build_with_defaults() -> Output<BuiltClContext> {
        let platforms = list_platforms()?;
        ClContextBuilder::build_from_platforms(&platforms[..])
    }

    pub unsafe fn build_from_platforms(platforms: &[ClPlatformID]) -> Output<BuiltClContext> {
        ClContextBuilder::build_from_platforms_with_device_type(platforms, DeviceType::ALL)
    }

    pub unsafe fn build_from_platforms_with_device_type(
        platforms: &[ClPlatformID],
        device_type: DeviceType,
    ) -> Output<BuiltClContext> {
        let mut devices = Vec::new();
        for p in platforms.iter() {
            let p_devices = list_devices_by_type(p, device_type)?;
            devices.extend(p_devices);
        }
        let context = ClContext::create(&devices[..])?;
        Ok(BuiltClContext::ContextWithDevices(context, devices))
    }

    pub unsafe fn build_from_devices(devices: &[ClDeviceID]) -> Output<BuiltClContext> {
        let context = ClContext::create(&devices[..])?;
        Ok(BuiltClContext::Context(context))
    }

    pub unsafe fn build_from_device_type(device_type: DeviceType) -> Output<BuiltClContext> {
        let platforms = list_platforms()?;
        ClContextBuilder::build_from_platforms_with_device_type(&platforms[..], device_type)
    }
}

pub enum BuiltClContext {
    Context(ClContext),
    ContextWithDevices(ClContext, Vec<ClDeviceID>),
}