mod error;
mod utility;
use std::{cmp, ffi, ops};
use super::Result;
use super::utility;
use super::super::sh;
pub fn init() -> Result {
unsafe {
let ret_value = sh::cuInit(0);
let err_message = "An error occurred while attempting to initialize the CUDA driver API";
return utility::check_with(ret_value, err_message, || {})
}
}
pub fn ndevices() -> Result<u32> {
unsafe {
let mut ndevices = 0;
let ret_value = sh::cuDeviceGetCount(&mut ndevices);
return utility::check(ret_value, || cmp::max(ndevices, 0) as u32)
}
}
#[derive(Debug)]
pub struct Context(sh::CUcontext);
impl Context {
pub fn destroy(&self) -> Result {
unsafe {
let ret_value = sh::cuCtxDestroy_v2(self.0);
return utility::check(ret_value, || {});
}
}
}
impl cmp::PartialEq<Context> for Context {
fn eq(&self, other: &Context) -> bool {
self.0 == other.0
}
}
impl ops::Drop for Context {
fn drop(&mut self) {
self.destroy().expect("failed to destroy CUDA context");
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Device(sh::CUdevice);
impl Device {
pub fn device(n: u32) -> Result<Device> {
unsafe {
let mut device_handle = 0;
let ret_value = sh::cuDeviceGet(&mut device_handle, n as i32);
return utility::check(ret_value, || Device(device_handle));
}
}
pub fn name(&self) -> Result<String> {
unsafe {
const LENGTH: i32 = 1024;
let mut array = [0; LENGTH as usize];
let name_pointer = array.as_mut_ptr();
let ret_value = sh::cuDeviceGetName(name_pointer, LENGTH, self.0);
return utility::check(ret_value, || {
let c_string = ffi::CString::from_raw(name_pointer);
let name = c_string.into_string()
.expect("an unexpected error occurred while retrieving the name of a device");
name
});
}
}
pub fn attribute(&self, attribute: sh::CUdevice_attribute) -> Result<i32> {
unsafe {
let mut pi = 0;
let ret_value = sh::cuDeviceGetAttribute(&mut pi, attribute, self.0);
return utility::check(ret_value, || pi)
}
}
pub fn max_threads_per_block(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAX_THREADS_PER_BLOCK)
}
pub fn max_block_dim_x(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAX_BLOCK_DIM_X)
}
pub fn max_block_dim_y(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAX_BLOCK_DIM_Y)
}
pub fn max_block_dim_z(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAX_BLOCK_DIM_Z)
}
pub fn max_grid_dim_x(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAX_GRID_DIM_X)
}
pub fn max_grid_dim_y(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAX_GRID_DIM_Y)
}
pub fn max_grid_dim_z(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAX_GRID_DIM_Z)
}
pub fn max_shared_memory_per_block(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAX_SHARED_MEMORY_PER_BLOCK)
}
pub fn total_constant_memory(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_TOTAL_CONSTANT_MEMORY)
}
pub fn warp_size(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_WARP_SIZE)
}
pub fn max_pitch(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAX_PITCH)
}
pub fn maximum_texture1d_width(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE1D_WIDTH)
}
pub fn maximum_texture1d_linear_width(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE1D_LINEAR_WIDTH)
}
pub fn maximum_texture1d_mipmapped_width(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE1D_MIPMAPPED_WIDTH)
}
pub fn maximum_texture2d_width(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE2D_WIDTH)
}
pub fn maximum_texture2d_height(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE2D_HEIGHT)
}
pub fn maximum_texture2d_linear_width(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE2D_LINEAR_WIDTH)
}
pub fn maximum_texture2d_linear_height(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE2D_LINEAR_HEIGHT)
}
pub fn maximum_texture2d_linear_pitch(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE2D_LINEAR_PITCH)
}
pub fn maximum_texture2d_mipmapped_width(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE2D_MIPMAPPED_WIDTH)
}
pub fn maximum_texture2d_mipmapped_height(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE2D_MIPMAPPED_HEIGHT)
}
pub fn maximum_texture3d_width(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE3D_WIDTH)
}
pub fn maximum_texture3d_height(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE3D_HEIGHT)
}
pub fn maximum_texture3d_depth(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE3D_DEPTH)
}
pub fn maximum_texture3d_width_alternate(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE3D_WIDTH_ALTERNATE)
}
pub fn maximum_texture3d_height_alternate(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE3D_HEIGHT_ALTERNATE)
}
pub fn maximum_texture3d_depth_alternate(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE3D_DEPTH_ALTERNATE)
}
pub fn maximum_texturecubemap_width(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURECUBEMAP_WIDTH)
}
pub fn maximum_texture1d_layered_width(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE1D_LAYERED_WIDTH)
}
pub fn maximum_texture1d_layered_layers(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE1D_LAYERED_LAYERS)
}
pub fn maximum_texture2d_layered_width(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE2D_LAYERED_WIDTH)
}
pub fn maximum_texture2d_layered_height(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE2D_LAYERED_HEIGHT)
}
pub fn maximum_texture2d_layered_layers(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE2D_LAYERED_LAYERS)
}
pub fn maximum_texturecubemap_layered_width(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURECUBEMAP_LAYERED_WIDTH)
}
pub fn maximum_texturecubemap_layered_layers(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURECUBEMAP_LAYERED_LAYERS)
}
pub fn maximum_surface1d_width(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAXIMUM_SURFACE1D_WIDTH)
}
pub fn maximum_surface2d_width(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAXIMUM_SURFACE2D_WIDTH)
}
pub fn maximum_surface2d_height(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAXIMUM_SURFACE2D_HEIGHT)
}
pub fn maximum_surface3d_width(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAXIMUM_SURFACE3D_WIDTH)
}
pub fn maximum_surface3d_height(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAXIMUM_SURFACE3D_HEIGHT)
}
pub fn maximum_surface3d_depth(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAXIMUM_SURFACE3D_DEPTH)
}
pub fn maximum_surface1d_layered_width(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAXIMUM_SURFACE1D_LAYERED_WIDTH)
}
pub fn maximum_surface1d_layered_layers(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAXIMUM_SURFACE1D_LAYERED_LAYERS)
}
pub fn maximum_surface2d_layered_width(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAXIMUM_SURFACE2D_LAYERED_WIDTH)
}
pub fn maximum_surface2d_layered_height(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAXIMUM_SURFACE2D_LAYERED_HEIGHT)
}
pub fn maximum_surface2d_layered_layers(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAXIMUM_SURFACE2D_LAYERED_LAYERS)
}
pub fn maximum_surfacecubemap_width(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAXIMUM_SURFACECUBEMAP_WIDTH)
}
pub fn maximum_surfacecubemap_layered_width(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAXIMUM_SURFACECUBEMAP_LAYERED_WIDTH)
}
pub fn maximum_surfacecubemap_layered_layers(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAXIMUM_SURFACECUBEMAP_LAYERED_LAYERS)
}
pub fn max_registers_per_block(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAX_REGISTERS_PER_BLOCK)
}
pub fn clock_rate(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_CLOCK_RATE)
}
pub fn texture_alignment(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_TEXTURE_ALIGNMENT)
}
pub fn texture_pitch_alignment(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_TEXTURE_PITCH_ALIGNMENT)
}
pub fn gpu_overlap(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_GPU_OVERLAP)
}
pub fn multiprocessor_count(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MULTIPROCESSOR_COUNT)
}
pub fn kernel_exec_timeout(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_KERNEL_EXEC_TIMEOUT)
}
pub fn integrated(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_INTEGRATED)
}
pub fn can_map_host_memory(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_CAN_MAP_HOST_MEMORY)
}
pub fn compute_mode(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_COMPUTE_MODE)
}
pub fn concurrent_kernels(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_CONCURRENT_KERNELS)
}
pub fn ecc_enabled(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_ECC_ENABLED)
}
pub fn pci_bus_id(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_PCI_BUS_ID)
}
pub fn pci_device_id(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_PCI_DEVICE_ID)
}
pub fn tcc_driver(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_TCC_DRIVER)
}
pub fn memory_clock_rate(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MEMORY_CLOCK_RATE)
}
pub fn global_memory_bus_width(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_GLOBAL_MEMORY_BUS_WIDTH)
}
pub fn l2_cache_size(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_L2_CACHE_SIZE)
}
pub fn max_threads_per_multiprocessor(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAX_THREADS_PER_MULTIPROCESSOR)
}
pub fn unified_addressing(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_UNIFIED_ADDRESSING)
}
pub fn compute_capability_major(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR)
}
pub fn compute_capability_minor(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR)
}
pub fn global_l1_cache_supported(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_GLOBAL_L1_CACHE_SUPPORTED)
}
pub fn local_l1_cache_supported(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_LOCAL_L1_CACHE_SUPPORTED)
}
pub fn max_shared_memory_per_multiprocessor(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAX_SHARED_MEMORY_PER_MULTIPROCESSOR)
}
pub fn max_registers_per_multiprocessor(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MAX_REGISTERS_PER_MULTIPROCESSOR)
}
pub fn managed_memory(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MANAGED_MEMORY)
}
pub fn multi_gpu_board(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MULTI_GPU_BOARD)
}
pub fn multi_gpu_board_group_id(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MULTI_GPU_BOARD_GROUP_ID)
}
pub fn host_native_atomic_supported(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_HOST_NATIVE_ATOMIC_SUPPORTED)
}
pub fn single_to_double_precision_perf_ratio(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_SINGLE_TO_DOUBLE_PRECISION_PERF_RATIO)
}
pub fn pageable_memory_access(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_PAGEABLE_MEMORY_ACCESS)
}
pub fn concurrent_managed_access(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_CONCURRENT_MANAGED_ACCESS)
}
pub fn compute_preemption_supported(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_COMPUTE_PREEMPTION_SUPPORTED)
}
pub fn can_use_host_pointer_for_registered_mem(&self) -> Result<i32> {
self.attribute(sh::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_CAN_USE_HOST_POINTER_FOR_REGISTERED_MEM)
}
}
#[derive(Debug)]
pub struct Memory(sh::CUdeviceptr);
impl Memory {
fn free(&self) -> Result {
unsafe {
let ret_value = sh::cuMemFree_v2(self.0);
return utility::check(ret_value, || {})
}
}
}
impl ops::Drop for Memory {
fn drop(&mut self) {
self.free().expect("failed to free CUDA memory")
}
}