use std::sync::Arc;
use baracuda_cuda_sys::runtime::runtime;
use baracuda_cuda_sys::CUgraphicsResource;
use crate::error::{check, Result};
use crate::stream::Stream;
pub use baracuda_cuda_sys::types::{
CUgraphicsMapResourceFlags as MapResourceFlags, CUgraphicsRegisterFlags as RegisterFlags,
};
#[derive(Clone)]
pub struct GraphicsResource {
inner: Arc<GraphicsResourceInner>,
}
struct GraphicsResourceInner {
handle: CUgraphicsResource,
}
unsafe impl Send for GraphicsResourceInner {}
unsafe impl Sync for GraphicsResourceInner {}
impl core::fmt::Debug for GraphicsResourceInner {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("GraphicsResource")
.field("handle", &self.handle)
.finish_non_exhaustive()
}
}
impl core::fmt::Debug for GraphicsResource {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
self.inner.fmt(f)
}
}
impl GraphicsResource {
pub unsafe fn from_raw(handle: CUgraphicsResource) -> Self {
Self {
inner: Arc::new(GraphicsResourceInner { handle }),
}
}
#[inline]
pub fn as_raw(&self) -> CUgraphicsResource {
self.inner.handle
}
pub fn set_map_flags(&self, flags: u32) -> Result<()> {
let r = runtime()?;
let cu = r.cuda_graphics_resource_set_map_flags()?;
check(unsafe { cu(self.inner.handle, flags) })
}
pub fn map(&self, stream: &Stream) -> Result<()> {
let r = runtime()?;
let cu = r.cuda_graphics_map_resources()?;
let mut arr = [self.inner.handle];
check(unsafe { cu(1, arr.as_mut_ptr(), stream.as_raw()) })
}
pub fn unmap(&self, stream: &Stream) -> Result<()> {
let r = runtime()?;
let cu = r.cuda_graphics_unmap_resources()?;
let mut arr = [self.inner.handle];
check(unsafe { cu(1, arr.as_mut_ptr(), stream.as_raw()) })
}
pub fn mapped_pointer(&self) -> Result<(*mut core::ffi::c_void, usize)> {
let r = runtime()?;
let cu = r.cuda_graphics_resource_get_mapped_pointer()?;
let mut dptr: *mut core::ffi::c_void = core::ptr::null_mut();
let mut size: usize = 0;
check(unsafe { cu(&mut dptr, &mut size, self.inner.handle) })?;
Ok((dptr, size))
}
pub fn mapped_array(&self, array_index: u32, mip_level: u32) -> Result<*mut core::ffi::c_void> {
let r = runtime()?;
let cu = r.cuda_graphics_sub_resource_get_mapped_array()?;
let mut arr: *mut core::ffi::c_void = core::ptr::null_mut();
check(unsafe { cu(&mut arr, self.inner.handle, array_index, mip_level) })?;
Ok(arr)
}
pub fn mapped_mipmapped_array(&self) -> Result<*mut core::ffi::c_void> {
let r = runtime()?;
let cu = r.cuda_graphics_resource_get_mapped_mipmapped_array()?;
let mut mip: *mut core::ffi::c_void = core::ptr::null_mut();
check(unsafe { cu(&mut mip, self.inner.handle) })?;
Ok(mip)
}
pub fn map_all(resources: &[Self], stream: &Stream) -> Result<()> {
if resources.is_empty() {
return Ok(());
}
let r = runtime()?;
let cu = r.cuda_graphics_map_resources()?;
let mut raws: Vec<CUgraphicsResource> = resources.iter().map(|x| x.as_raw()).collect();
check(unsafe {
cu(
raws.len() as core::ffi::c_int,
raws.as_mut_ptr(),
stream.as_raw(),
)
})
}
pub fn unmap_all(resources: &[Self], stream: &Stream) -> Result<()> {
if resources.is_empty() {
return Ok(());
}
let r = runtime()?;
let cu = r.cuda_graphics_unmap_resources()?;
let mut raws: Vec<CUgraphicsResource> = resources.iter().map(|x| x.as_raw()).collect();
check(unsafe {
cu(
raws.len() as core::ffi::c_int,
raws.as_mut_ptr(),
stream.as_raw(),
)
})
}
}
impl Drop for GraphicsResourceInner {
fn drop(&mut self) {
if self.handle.is_null() {
return;
}
if let Ok(r) = runtime() {
if let Ok(cu) = r.cuda_graphics_unregister_resource() {
let _ = unsafe { cu(self.handle) };
}
}
}
}
pub mod gl {
use super::*;
use baracuda_cuda_sys::types::{GLenum, GLuint};
pub fn get_devices(device_list: u32) -> Result<Vec<i32>> {
let r = runtime()?;
let cu = r.cuda_gl_get_devices()?;
let mut count: core::ffi::c_uint = 0;
let probe_rc = unsafe { cu(&mut count, core::ptr::null_mut(), 0, device_list) };
if probe_rc != baracuda_cuda_sys::runtime::cudaError_t::Success {
return Ok(Vec::new());
}
if count == 0 {
return Ok(Vec::new());
}
let mut out = vec![0i32; count as usize];
check(unsafe {
cu(
&mut count,
out.as_mut_ptr(),
out.len() as core::ffi::c_uint,
device_list,
)
})?;
out.truncate(count as usize);
Ok(out)
}
pub unsafe fn register_buffer(buffer: GLuint, flags: u32) -> Result<GraphicsResource> { unsafe {
let r = runtime()?;
let cu = r.cuda_graphics_gl_register_buffer()?;
let mut res: CUgraphicsResource = core::ptr::null_mut();
check(cu(&mut res, buffer, flags))?;
Ok(GraphicsResource::from_raw(res))
}}
pub unsafe fn register_image(
image: GLuint,
target: GLenum,
flags: u32,
) -> Result<GraphicsResource> { unsafe {
let r = runtime()?;
let cu = r.cuda_graphics_gl_register_image()?;
let mut res: CUgraphicsResource = core::ptr::null_mut();
check(cu(&mut res, image, target, flags))?;
Ok(GraphicsResource::from_raw(res))
}}
}
pub mod d3d9 {
use super::*;
pub unsafe fn get_device(adapter_name: *const core::ffi::c_char) -> Result<i32> { unsafe {
let r = runtime()?;
let cu = r.cuda_d3d9_get_device()?;
let mut dev: core::ffi::c_int = 0;
check(cu(&mut dev, adapter_name))?;
Ok(dev)
}}
pub unsafe fn get_devices(
d3d_device: *mut core::ffi::c_void,
device_list: u32,
) -> Result<Vec<i32>> { unsafe {
let r = runtime()?;
let cu = r.cuda_d3d9_get_devices()?;
let mut count: core::ffi::c_uint = 0;
check(cu(
&mut count,
core::ptr::null_mut(),
0,
d3d_device,
device_list,
))?;
if count == 0 {
return Ok(Vec::new());
}
let mut out = vec![0i32; count as usize];
check(cu(
&mut count,
out.as_mut_ptr(),
out.len() as core::ffi::c_uint,
d3d_device,
device_list,
))?;
out.truncate(count as usize);
Ok(out)
}}
pub unsafe fn register_resource(
resource: *mut core::ffi::c_void,
flags: u32,
) -> Result<GraphicsResource> { unsafe {
let r = runtime()?;
let cu = r.cuda_graphics_d3d9_register_resource()?;
let mut res: CUgraphicsResource = core::ptr::null_mut();
check(cu(&mut res, resource, flags))?;
Ok(GraphicsResource::from_raw(res))
}}
}
pub mod d3d10 {
use super::*;
pub unsafe fn get_device(adapter: *mut core::ffi::c_void) -> Result<i32> { unsafe {
let r = runtime()?;
let cu = r.cuda_d3d10_get_device()?;
let mut dev: core::ffi::c_int = 0;
check(cu(&mut dev, adapter))?;
Ok(dev)
}}
pub unsafe fn get_devices(
d3d_device: *mut core::ffi::c_void,
device_list: u32,
) -> Result<Vec<i32>> { unsafe {
let r = runtime()?;
let cu = r.cuda_d3d10_get_devices()?;
let mut count: core::ffi::c_uint = 0;
check(cu(
&mut count,
core::ptr::null_mut(),
0,
d3d_device,
device_list,
))?;
if count == 0 {
return Ok(Vec::new());
}
let mut out = vec![0i32; count as usize];
check(cu(
&mut count,
out.as_mut_ptr(),
out.len() as core::ffi::c_uint,
d3d_device,
device_list,
))?;
out.truncate(count as usize);
Ok(out)
}}
pub unsafe fn register_resource(
resource: *mut core::ffi::c_void,
flags: u32,
) -> Result<GraphicsResource> { unsafe {
let r = runtime()?;
let cu = r.cuda_graphics_d3d10_register_resource()?;
let mut res: CUgraphicsResource = core::ptr::null_mut();
check(cu(&mut res, resource, flags))?;
Ok(GraphicsResource::from_raw(res))
}}
}
pub mod d3d11 {
use super::*;
pub unsafe fn get_device(adapter: *mut core::ffi::c_void) -> Result<i32> { unsafe {
let r = runtime()?;
let cu = r.cuda_d3d11_get_device()?;
let mut dev: core::ffi::c_int = 0;
check(cu(&mut dev, adapter))?;
Ok(dev)
}}
pub unsafe fn get_devices(
d3d_device: *mut core::ffi::c_void,
device_list: u32,
) -> Result<Vec<i32>> { unsafe {
let r = runtime()?;
let cu = r.cuda_d3d11_get_devices()?;
let mut count: core::ffi::c_uint = 0;
check(cu(
&mut count,
core::ptr::null_mut(),
0,
d3d_device,
device_list,
))?;
if count == 0 {
return Ok(Vec::new());
}
let mut out = vec![0i32; count as usize];
check(cu(
&mut count,
out.as_mut_ptr(),
out.len() as core::ffi::c_uint,
d3d_device,
device_list,
))?;
out.truncate(count as usize);
Ok(out)
}}
pub unsafe fn register_resource(
resource: *mut core::ffi::c_void,
flags: u32,
) -> Result<GraphicsResource> { unsafe {
let r = runtime()?;
let cu = r.cuda_graphics_d3d11_register_resource()?;
let mut res: CUgraphicsResource = core::ptr::null_mut();
check(cu(&mut res, resource, flags))?;
Ok(GraphicsResource::from_raw(res))
}}
}
pub mod vdpau {
use super::*;
pub unsafe fn get_device(
vdp_device: *mut core::ffi::c_void,
vdp_get_proc_address: *mut core::ffi::c_void,
) -> Result<i32> { unsafe {
let r = runtime()?;
let cu = r.cuda_vdpau_get_device()?;
let mut dev: core::ffi::c_int = 0;
check(cu(&mut dev, vdp_device, vdp_get_proc_address))?;
Ok(dev)
}}
pub unsafe fn register_video_surface(
vdp_surface: *mut core::ffi::c_void,
flags: u32,
) -> Result<GraphicsResource> { unsafe {
let r = runtime()?;
let cu = r.cuda_graphics_vdpau_register_video_surface()?;
let mut res: CUgraphicsResource = core::ptr::null_mut();
check(cu(&mut res, vdp_surface, flags))?;
Ok(GraphicsResource::from_raw(res))
}}
pub unsafe fn register_output_surface(
vdp_surface: *mut core::ffi::c_void,
flags: u32,
) -> Result<GraphicsResource> { unsafe {
let r = runtime()?;
let cu = r.cuda_graphics_vdpau_register_output_surface()?;
let mut res: CUgraphicsResource = core::ptr::null_mut();
check(cu(&mut res, vdp_surface, flags))?;
Ok(GraphicsResource::from_raw(res))
}}
}
pub mod egl {
use super::*;
use baracuda_cuda_sys::runtime::cudaEvent_t;
use core::ffi::c_void;
pub unsafe fn register_image(image: *mut c_void, flags: u32) -> Result<GraphicsResource> { unsafe {
let r = runtime()?;
let cu = r.cuda_graphics_egl_register_image()?;
let mut res: CUgraphicsResource = core::ptr::null_mut();
check(cu(&mut res, image, flags))?;
Ok(GraphicsResource::from_raw(res))
}}
pub unsafe fn mapped_frame(
resource: &GraphicsResource,
egl_frame_out: *mut c_void,
index: u32,
mip_level: u32,
) -> Result<()> { unsafe {
let r = runtime()?;
let cu = r.cuda_graphics_resource_get_mapped_egl_frame()?;
check(cu(egl_frame_out, resource.as_raw(), index, mip_level))
}}
pub unsafe fn event_from_sync(egl_sync: *mut c_void, flags: u32) -> Result<cudaEvent_t> { unsafe {
let r = runtime()?;
let cu = r.cuda_event_create_from_egl_sync()?;
let mut event: cudaEvent_t = core::ptr::null_mut();
check(cu(&mut event, egl_sync, flags))?;
Ok(event)
}}
pub unsafe fn stream_consumer_connect(
connection: *mut c_void,
egl_stream: *mut c_void,
) -> Result<()> { unsafe {
let r = runtime()?;
let cu = r.cuda_egl_stream_consumer_connect()?;
check(cu(connection, egl_stream))
}}
pub unsafe fn stream_consumer_disconnect(connection: *mut c_void) -> Result<()> { unsafe {
let r = runtime()?;
let cu = r.cuda_egl_stream_consumer_disconnect()?;
check(cu(connection))
}}
pub unsafe fn stream_consumer_acquire_frame(
connection: *mut c_void,
stream_out: *mut baracuda_cuda_sys::runtime::cudaStream_t,
timeout: u32,
) -> Result<GraphicsResource> { unsafe {
let r = runtime()?;
let cu = r.cuda_egl_stream_consumer_acquire_frame()?;
let mut res: CUgraphicsResource = core::ptr::null_mut();
check(cu(connection, &mut res, stream_out, timeout))?;
Ok(GraphicsResource::from_raw(res))
}}
pub unsafe fn stream_consumer_release_frame(
connection: *mut c_void,
resource: &GraphicsResource,
stream_inout: *mut baracuda_cuda_sys::runtime::cudaStream_t,
) -> Result<()> { unsafe {
let r = runtime()?;
let cu = r.cuda_egl_stream_consumer_release_frame()?;
check(cu(connection, resource.as_raw(), stream_inout))
}}
pub unsafe fn stream_producer_connect(
connection: *mut c_void,
egl_stream: *mut c_void,
width: i32,
height: i32,
) -> Result<()> { unsafe {
let r = runtime()?;
let cu = r.cuda_egl_stream_producer_connect()?;
check(cu(connection, egl_stream, width, height))
}}
pub unsafe fn stream_producer_disconnect(connection: *mut c_void) -> Result<()> { unsafe {
let r = runtime()?;
let cu = r.cuda_egl_stream_producer_disconnect()?;
check(cu(connection))
}}
pub unsafe fn stream_producer_present_frame(
connection: *mut c_void,
egl_frame: *mut c_void,
stream_inout: *mut baracuda_cuda_sys::runtime::cudaStream_t,
) -> Result<()> { unsafe {
let r = runtime()?;
let cu = r.cuda_egl_stream_producer_present_frame()?;
check(cu(connection, egl_frame, stream_inout))
}}
pub unsafe fn stream_producer_return_frame(
connection: *mut c_void,
egl_frame_out: *mut c_void,
stream_inout: *mut baracuda_cuda_sys::runtime::cudaStream_t,
) -> Result<()> { unsafe {
let r = runtime()?;
let cu = r.cuda_egl_stream_producer_return_frame()?;
check(cu(connection, egl_frame_out, stream_inout))
}}
}
pub mod nvsci {
use super::*;
use crate::device::Device;
pub const SIGNAL: i32 = 0;
pub const WAIT: i32 = 1;
pub unsafe fn device_sync_attributes(
attr_list: *mut core::ffi::c_void,
device: &Device,
direction: i32,
) -> Result<()> { unsafe {
let r = runtime()?;
let cu = r.cuda_device_get_nv_sci_sync_attributes()?;
check(cu(attr_list, device.ordinal(), direction))
}}
}