use std::{
mem::{ManuallyDrop, MaybeUninit},
os::raw::c_ulonglong,
};
use crate::sys::{
cuSurfObjectCreate, cuSurfObjectDestroy, cuSurfObjectGetResourceDesc, CUsurfObject,
CUDA_RESOURCE_DESC,
};
use crate::{
error::{CudaResult, ToResult},
memory::array::ArrayObject,
texture::{ResourceDescriptor, ResourceDescriptorFlags, ResourceType},
};
pub struct Surface {
_destroy_array_on_drop: bool,
handle: CUsurfObject,
}
impl Drop for Surface {
fn drop(&mut self) {
unsafe {
if false {
let res = self.resource_desc();
if let Ok(res) = res {
let _ = ManuallyDrop::into_inner(res);
}
}
cuSurfObjectDestroy(self.handle);
}
}
}
pub type SurfaceHandle = c_ulonglong;
impl Surface {
pub fn handle(&self) -> SurfaceHandle {
self.handle
}
pub fn new(resource_desc: ResourceDescriptor) -> CudaResult<Self> {
let raw = resource_desc.into_raw();
unsafe {
let mut uninit = MaybeUninit::<CUsurfObject>::uninit();
cuSurfObjectCreate(uninit.as_mut_ptr(), &raw as *const _).to_result()?;
Ok(Self {
handle: uninit.assume_init(),
_destroy_array_on_drop: true,
})
}
}
pub fn from_array(array: ArrayObject) -> CudaResult<Self> {
let resource_desc = ResourceDescriptor {
flags: ResourceDescriptorFlags::empty(),
ty: ResourceType::Array { array },
};
Self::new(resource_desc)
}
pub fn into_array(mut self) -> CudaResult<Option<ArrayObject>> {
let desc = unsafe { ManuallyDrop::take(&mut self.resource_desc()?) };
self._destroy_array_on_drop = false;
Ok(match desc.ty {
ResourceType::Array { array } => Some(array),
})
}
unsafe fn resource_desc(&mut self) -> CudaResult<ManuallyDrop<ResourceDescriptor>> {
let raw = {
let mut uninit = MaybeUninit::<CUDA_RESOURCE_DESC>::uninit();
cuSurfObjectGetResourceDesc(uninit.as_mut_ptr(), self.handle).to_result()?;
uninit.assume_init()
};
Ok(ManuallyDrop::new(ResourceDescriptor::from_raw(raw)))
}
}