use std::sync::Arc;
use baracuda_cuda_sys::types::{CUdevResource, CUdevResourceType, CUdevSmResource};
use baracuda_cuda_sys::{driver, CUcontext, CUdevResourceDesc, CUgreenCtx, CUstream};
use crate::device::Device;
use crate::error::{check, Result};
pub fn device_sm_resource(device: &Device) -> Result<CUdevResource> {
let d = driver()?;
let cu = d.cu_device_get_dev_resource()?;
let mut r = CUdevResource::default();
check(unsafe { cu(device.as_raw(), &mut r, CUdevResourceType::SM) })?;
Ok(r)
}
pub fn sm_resource_split_by_count(
input: &CUdevResource,
min_count: u32,
) -> Result<(Vec<CUdevResource>, CUdevResource)> {
let d = driver()?;
let cu = d.cu_dev_sm_resource_split_by_count()?;
let mut nb: core::ffi::c_uint = 0;
let mut remaining = CUdevResource::default();
check(unsafe {
cu(
core::ptr::null_mut(),
&mut nb,
input,
&mut remaining,
0,
min_count,
)
})?;
let mut result = vec![CUdevResource::default(); nb as usize];
if nb > 0 {
check(unsafe {
cu(
result.as_mut_ptr(),
&mut nb,
input,
&mut remaining,
0,
min_count,
)
})?;
}
Ok((result, remaining))
}
#[derive(Clone)]
pub struct GreenContext {
inner: Arc<GreenContextInner>,
}
struct GreenContextInner {
handle: CUgreenCtx,
}
unsafe impl Send for GreenContextInner {}
unsafe impl Sync for GreenContextInner {}
impl core::fmt::Debug for GreenContextInner {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("GreenContext")
.field("handle", &self.handle)
.finish_non_exhaustive()
}
}
impl core::fmt::Debug for GreenContext {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
self.inner.fmt(f)
}
}
impl GreenContext {
pub fn from_resource(device: &Device, mut resource: CUdevResource) -> Result<Self> {
let d = driver()?;
let gen = d.cu_dev_resource_generate_desc()?;
let mut desc: CUdevResourceDesc = core::ptr::null_mut();
check(unsafe { gen(&mut desc, &mut resource, 1) })?;
let create = d.cu_green_ctx_create()?;
let mut handle: CUgreenCtx = core::ptr::null_mut();
check(unsafe { create(&mut handle, desc, device.as_raw(), 0) })?;
Ok(Self {
inner: Arc::new(GreenContextInner { handle }),
})
}
pub fn as_ctx_raw(&self) -> Result<CUcontext> {
let d = driver()?;
let cu = d.cu_ctx_from_green_ctx()?;
let mut out: CUcontext = core::ptr::null_mut();
check(unsafe { cu(&mut out, self.inner.handle) })?;
Ok(out)
}
pub fn sm_resource(&self) -> Result<CUdevSmResource> {
let d = driver()?;
let cu = d.cu_green_ctx_get_dev_resource()?;
let mut r = CUdevResource::default();
check(unsafe { cu(self.inner.handle, &mut r, CUdevResourceType::SM) })?;
Ok(r.as_sm())
}
pub fn create_stream_raw(&self, flags: u32, priority: i32) -> Result<CUstream> {
let d = driver()?;
let cu = d.cu_green_ctx_stream_create()?;
let mut s: CUstream = core::ptr::null_mut();
check(unsafe { cu(&mut s, self.inner.handle, flags, priority) })?;
Ok(s)
}
pub unsafe fn from_raw(handle: CUgreenCtx) -> Self {
Self {
inner: Arc::new(GreenContextInner { handle }),
}
}
pub fn into_raw(self) -> CUgreenCtx {
match Arc::try_unwrap(self.inner) {
Ok(mut inner) => {
let h = inner.handle;
inner.handle = core::ptr::null_mut();
h
}
Err(arc) => arc.handle,
}
}
#[inline]
pub fn as_raw(&self) -> CUgreenCtx {
self.inner.handle
}
}
impl Drop for GreenContextInner {
fn drop(&mut self) {
if self.handle.is_null() {
return;
}
if let Ok(d) = driver() {
if let Ok(cu) = d.cu_green_ctx_destroy() {
let _ = unsafe { cu(self.handle) };
}
}
}
}