use std::sync::Arc;
use baracuda_cuda_sys::types::CUmipmappedArray;
use baracuda_cuda_sys::{driver, CUarray, CUdeviceptr, CUgraphicsResource};
use crate::context::Context;
use crate::error::{check, Result};
use crate::stream::Stream;
pub use baracuda_cuda_sys::types::{
CUGLDeviceList as GLDeviceList, CUgraphicsMapResourceFlags as MapResourceFlags,
CUgraphicsRegisterFlags as RegisterFlags,
};
#[derive(Clone)]
pub struct GraphicsResource {
inner: Arc<GraphicsResourceInner>,
}
struct GraphicsResourceInner {
handle: CUgraphicsResource,
#[allow(dead_code)]
context: Context,
}
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(context: &Context, handle: CUgraphicsResource) -> Self {
Self {
inner: Arc::new(GraphicsResourceInner {
handle,
context: context.clone(),
}),
}
}
#[inline]
pub fn as_raw(&self) -> CUgraphicsResource {
self.inner.handle
}
pub fn set_map_flags(&self, flags: u32) -> Result<()> {
let d = driver()?;
let cu = d.cu_graphics_resource_set_map_flags()?;
check(unsafe { cu(self.inner.handle, flags) })
}
pub fn map(&self, stream: &Stream) -> Result<()> {
let d = driver()?;
let cu = d.cu_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 d = driver()?;
let cu = d.cu_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<(CUdeviceptr, usize)> {
let d = driver()?;
let cu = d.cu_graphics_resource_get_mapped_pointer()?;
let mut dptr = CUdeviceptr(0);
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<CUarray> {
let d = driver()?;
let cu = d.cu_graphics_sub_resource_get_mapped_array()?;
let mut arr: CUarray = 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<CUmipmappedArray> {
let d = driver()?;
let cu = d.cu_graphics_resource_get_mapped_mipmapped_array()?;
let mut mip: CUmipmappedArray = 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 d = driver()?;
let cu = d.cu_graphics_map_resources()?;
let mut raws: Vec<CUgraphicsResource> = resources.iter().map(|r| r.as_raw()).collect();
check(unsafe {
cu(
raws.len() as core::ffi::c_uint,
raws.as_mut_ptr(),
stream.as_raw(),
)
})
}
pub fn unmap_all(resources: &[Self], stream: &Stream) -> Result<()> {
if resources.is_empty() {
return Ok(());
}
let d = driver()?;
let cu = d.cu_graphics_unmap_resources()?;
let mut raws: Vec<CUgraphicsResource> = resources.iter().map(|r| r.as_raw()).collect();
check(unsafe {
cu(
raws.len() as core::ffi::c_uint,
raws.as_mut_ptr(),
stream.as_raw(),
)
})
}
}
impl Drop for GraphicsResourceInner {
fn drop(&mut self) {
if self.handle.is_null() {
return;
}
if let Ok(d) = driver() {
if let Ok(cu) = d.cu_graphics_unregister_resource() {
let _ = unsafe { cu(self.handle) };
}
}
}
}
pub mod gl {
use super::*;
use crate::device::Device;
use baracuda_cuda_sys::types::{GLenum, GLuint};
pub fn init() -> Result<()> {
let d = driver()?;
let cu = d.cu_gl_init()?;
check(unsafe { cu() })
}
pub fn get_devices(device_list: u32) -> Result<Vec<Device>> {
let d = driver()?;
let cu = d.cu_gl_get_devices()?;
let mut count: core::ffi::c_uint = 0;
let probe = unsafe { cu(&mut count, core::ptr::null_mut(), 0, device_list) };
if !probe.is_success() && probe != baracuda_cuda_sys::CUresult::ERROR_NOT_INITIALIZED {
check(probe)?;
}
if count == 0 {
return Ok(Vec::new());
}
let mut raw = vec![baracuda_cuda_sys::CUdevice(0); count as usize];
check(unsafe {
cu(
&mut count,
raw.as_mut_ptr(),
raw.len() as core::ffi::c_uint,
device_list,
)
})?;
Ok(raw.into_iter().map(Device).collect())
}
pub unsafe fn register_buffer(
context: &Context,
buffer: GLuint,
flags: u32,
) -> Result<GraphicsResource> { unsafe {
context.set_current()?;
let d = driver()?;
let cu = d.cu_graphics_gl_register_buffer()?;
let mut resource: CUgraphicsResource = core::ptr::null_mut();
check(cu(&mut resource, buffer, flags))?;
Ok(GraphicsResource::from_raw(context, resource))
}}
pub unsafe fn register_image(
context: &Context,
image: GLuint,
target: GLenum,
flags: u32,
) -> Result<GraphicsResource> { unsafe {
context.set_current()?;
let d = driver()?;
let cu = d.cu_graphics_gl_register_image()?;
let mut resource: CUgraphicsResource = core::ptr::null_mut();
check(cu(&mut resource, image, target, flags))?;
Ok(GraphicsResource::from_raw(context, resource))
}}
}
pub mod d3d9 {
use super::*;
use crate::device::Device;
use baracuda_cuda_sys::types::{ID3DDevice, ID3DResource};
pub unsafe fn get_device(adapter_name: *const core::ffi::c_char) -> Result<Device> { unsafe {
let d = driver()?;
let cu = d.cu_d3d9_get_device()?;
let mut dev = baracuda_cuda_sys::CUdevice(0);
check(cu(&mut dev, adapter_name))?;
Ok(Device(dev))
}}
pub unsafe fn get_devices(d3d_device: ID3DDevice, device_list: u32) -> Result<Vec<Device>> { unsafe {
let d = driver()?;
let cu = d.cu_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 raw = vec![baracuda_cuda_sys::CUdevice(0); count as usize];
check(cu(
&mut count,
raw.as_mut_ptr(),
raw.len() as core::ffi::c_uint,
d3d_device,
device_list,
))?;
Ok(raw.into_iter().map(Device).collect())
}}
pub unsafe fn register_resource(
context: &Context,
resource: ID3DResource,
flags: u32,
) -> Result<GraphicsResource> { unsafe {
context.set_current()?;
let d = driver()?;
let cu = d.cu_graphics_d3d9_register_resource()?;
let mut res: CUgraphicsResource = core::ptr::null_mut();
check(cu(&mut res, resource, flags))?;
Ok(GraphicsResource::from_raw(context, res))
}}
}
pub mod d3d10 {
use super::*;
use crate::device::Device;
use baracuda_cuda_sys::types::{ID3DDevice, ID3DResource};
pub unsafe fn get_device(adapter: ID3DDevice) -> Result<Device> { unsafe {
let d = driver()?;
let cu = d.cu_d3d10_get_device()?;
let mut dev = baracuda_cuda_sys::CUdevice(0);
check(cu(&mut dev, adapter))?;
Ok(Device(dev))
}}
pub unsafe fn get_devices(d3d_device: ID3DDevice, device_list: u32) -> Result<Vec<Device>> { unsafe {
let d = driver()?;
let cu = d.cu_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 raw = vec![baracuda_cuda_sys::CUdevice(0); count as usize];
check(cu(
&mut count,
raw.as_mut_ptr(),
raw.len() as core::ffi::c_uint,
d3d_device,
device_list,
))?;
Ok(raw.into_iter().map(Device).collect())
}}
pub unsafe fn register_resource(
context: &Context,
resource: ID3DResource,
flags: u32,
) -> Result<GraphicsResource> { unsafe {
context.set_current()?;
let d = driver()?;
let cu = d.cu_graphics_d3d10_register_resource()?;
let mut res: CUgraphicsResource = core::ptr::null_mut();
check(cu(&mut res, resource, flags))?;
Ok(GraphicsResource::from_raw(context, res))
}}
}
pub mod vdpau {
use super::*;
use crate::device::Device;
use baracuda_cuda_sys::types::{
VdpDevice, VdpGetProcAddress, VdpOutputSurface, VdpVideoSurface,
};
pub unsafe fn get_device(
vdp_device: VdpDevice,
vdp_get_proc_address: VdpGetProcAddress,
) -> Result<Device> { unsafe {
let d = driver()?;
let cu = d.cu_vdpau_get_device()?;
let mut dev = baracuda_cuda_sys::CUdevice(0);
check(cu(&mut dev, vdp_device, vdp_get_proc_address))?;
Ok(Device(dev))
}}
pub unsafe fn register_video_surface(
context: &Context,
vdp_surface: VdpVideoSurface,
flags: u32,
) -> Result<GraphicsResource> { unsafe {
context.set_current()?;
let d = driver()?;
let cu = d.cu_graphics_vdpau_register_video_surface()?;
let mut res: CUgraphicsResource = core::ptr::null_mut();
check(cu(&mut res, vdp_surface, flags))?;
Ok(GraphicsResource::from_raw(context, res))
}}
pub unsafe fn register_output_surface(
context: &Context,
vdp_surface: VdpOutputSurface,
flags: u32,
) -> Result<GraphicsResource> { unsafe {
context.set_current()?;
let d = driver()?;
let cu = d.cu_graphics_vdpau_register_output_surface()?;
let mut res: CUgraphicsResource = core::ptr::null_mut();
check(cu(&mut res, vdp_surface, flags))?;
Ok(GraphicsResource::from_raw(context, res))
}}
}
pub mod egl {
use super::*;
use baracuda_cuda_sys::types::{CUeglFrame, EGLImageKHR, EGLStreamKHR, EGLSyncKHR};
use baracuda_cuda_sys::CUevent;
use core::ffi::c_void;
pub unsafe fn register_image(
context: &Context,
image: EGLImageKHR,
flags: u32,
) -> Result<GraphicsResource> { unsafe {
context.set_current()?;
let d = driver()?;
let cu = d.cu_graphics_egl_register_image()?;
let mut res: CUgraphicsResource = core::ptr::null_mut();
check(cu(&mut res, image, flags))?;
Ok(GraphicsResource::from_raw(context, res))
}}
pub fn mapped_frame(
resource: &GraphicsResource,
index: u32,
mip_level: u32,
) -> Result<CUeglFrame> {
let d = driver()?;
let cu = d.cu_graphics_resource_get_mapped_egl_frame()?;
let mut frame = CUeglFrame::default();
check(unsafe { cu(&mut frame, resource.as_raw(), index, mip_level) })?;
Ok(frame)
}
pub unsafe fn event_from_sync(egl_sync: EGLSyncKHR, flags: u32) -> Result<CUevent> { unsafe {
let d = driver()?;
let cu = d.cu_event_create_from_egl_sync()?;
let mut event: CUevent = core::ptr::null_mut();
check(cu(&mut event, egl_sync, flags))?;
Ok(event)
}}
pub unsafe fn stream_consumer_connect(
connection: *mut c_void,
stream: EGLStreamKHR,
) -> Result<()> { unsafe {
let d = driver()?;
let cu = d.cu_egl_stream_consumer_connect()?;
check(cu(connection, stream))
}}
pub unsafe fn stream_consumer_disconnect(connection: *mut c_void) -> Result<()> { unsafe {
let d = driver()?;
let cu = d.cu_egl_stream_consumer_disconnect()?;
check(cu(connection))
}}
pub unsafe fn stream_consumer_acquire_frame(
context: &Context,
connection: *mut c_void,
cu_stream_out: *mut baracuda_cuda_sys::CUstream,
timeout: u32,
) -> Result<GraphicsResource> { unsafe {
let d = driver()?;
let cu = d.cu_egl_stream_consumer_acquire_frame()?;
let mut resource: CUgraphicsResource = core::ptr::null_mut();
check(cu(connection, &mut resource, cu_stream_out, timeout))?;
Ok(GraphicsResource::from_raw(context, resource))
}}
pub unsafe fn stream_consumer_release_frame(
connection: *mut c_void,
resource: &GraphicsResource,
cu_stream_inout: *mut baracuda_cuda_sys::CUstream,
) -> Result<()> { unsafe {
let d = driver()?;
let cu = d.cu_egl_stream_consumer_release_frame()?;
check(cu(connection, resource.as_raw(), cu_stream_inout))
}}
pub unsafe fn stream_producer_connect(
connection: *mut c_void,
stream: EGLStreamKHR,
width: i32,
height: i32,
) -> Result<()> { unsafe {
let d = driver()?;
let cu = d.cu_egl_stream_producer_connect()?;
check(cu(connection, stream, width, height))
}}
pub unsafe fn stream_producer_disconnect(connection: *mut c_void) -> Result<()> { unsafe {
let d = driver()?;
let cu = d.cu_egl_stream_producer_disconnect()?;
check(cu(connection))
}}
pub unsafe fn stream_producer_present_frame(
connection: *mut c_void,
egl_frame: CUeglFrame,
cu_stream_inout: *mut baracuda_cuda_sys::CUstream,
) -> Result<()> { unsafe {
let d = driver()?;
let cu = d.cu_egl_stream_producer_present_frame()?;
check(cu(connection, egl_frame, cu_stream_inout))
}}
pub unsafe fn stream_producer_return_frame(
connection: *mut c_void,
egl_frame: *mut CUeglFrame,
cu_stream_inout: *mut baracuda_cuda_sys::CUstream,
) -> Result<()> { unsafe {
let d = driver()?;
let cu = d.cu_egl_stream_producer_return_frame()?;
check(cu(connection, egl_frame, cu_stream_inout))
}}
}
pub mod nvsci {
use super::*;
use crate::device::Device;
use baracuda_cuda_sys::types::NvSciSyncAttrList;
pub const SIGNAL: i32 = baracuda_cuda_sys::types::CUnvSciSyncAttr::SIGNAL;
pub const WAIT: i32 = baracuda_cuda_sys::types::CUnvSciSyncAttr::WAIT;
pub unsafe fn device_sync_attributes(
attr_list: NvSciSyncAttrList,
device: &Device,
direction: i32,
) -> Result<()> { unsafe {
let d = driver()?;
let cu = d.cu_device_get_nv_sci_sync_attributes()?;
check(cu(attr_list, device.as_raw(), direction))
}}
}
pub mod d3d11 {
use super::*;
use crate::device::Device;
use baracuda_cuda_sys::types::{ID3DDevice, ID3DResource};
pub unsafe fn get_device(adapter: ID3DDevice) -> Result<Device> { unsafe {
let d = driver()?;
let cu = d.cu_d3d11_get_device()?;
let mut dev = baracuda_cuda_sys::CUdevice(0);
check(cu(&mut dev, adapter))?;
Ok(Device(dev))
}}
pub unsafe fn get_devices(d3d_device: ID3DDevice, device_list: u32) -> Result<Vec<Device>> { unsafe {
let d = driver()?;
let cu = d.cu_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 raw = vec![baracuda_cuda_sys::CUdevice(0); count as usize];
check(cu(
&mut count,
raw.as_mut_ptr(),
raw.len() as core::ffi::c_uint,
d3d_device,
device_list,
))?;
Ok(raw.into_iter().map(Device).collect())
}}
pub unsafe fn register_resource(
context: &Context,
resource: ID3DResource,
flags: u32,
) -> Result<GraphicsResource> { unsafe {
context.set_current()?;
let d = driver()?;
let cu = d.cu_graphics_d3d11_register_resource()?;
let mut res: CUgraphicsResource = core::ptr::null_mut();
check(cu(&mut res, resource, flags))?;
Ok(GraphicsResource::from_raw(context, res))
}}
}