1use std::sync::Arc;
27
28use baracuda_cuda_sys::types::CUmipmappedArray;
29use baracuda_cuda_sys::{driver, CUarray, CUdeviceptr, CUgraphicsResource};
30
31use crate::context::Context;
32use crate::error::{check, Result};
33use crate::stream::Stream;
34
35pub use baracuda_cuda_sys::types::{
36 CUGLDeviceList as GLDeviceList, CUgraphicsMapResourceFlags as MapResourceFlags,
37 CUgraphicsRegisterFlags as RegisterFlags,
38};
39
40#[derive(Clone)]
43pub struct GraphicsResource {
44 inner: Arc<GraphicsResourceInner>,
45}
46
47struct GraphicsResourceInner {
48 handle: CUgraphicsResource,
49 #[allow(dead_code)]
50 context: Context,
51}
52
53unsafe impl Send for GraphicsResourceInner {}
54unsafe impl Sync for GraphicsResourceInner {}
55
56impl core::fmt::Debug for GraphicsResourceInner {
57 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
58 f.debug_struct("GraphicsResource")
59 .field("handle", &self.handle)
60 .finish_non_exhaustive()
61 }
62}
63
64impl core::fmt::Debug for GraphicsResource {
65 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
66 self.inner.fmt(f)
67 }
68}
69
70impl GraphicsResource {
71 pub unsafe fn from_raw(context: &Context, handle: CUgraphicsResource) -> Self {
79 Self {
80 inner: Arc::new(GraphicsResourceInner {
81 handle,
82 context: context.clone(),
83 }),
84 }
85 }
86
87 #[inline]
88 pub fn as_raw(&self) -> CUgraphicsResource {
89 self.inner.handle
90 }
91
92 pub fn set_map_flags(&self, flags: u32) -> Result<()> {
95 let d = driver()?;
96 let cu = d.cu_graphics_resource_set_map_flags()?;
97 check(unsafe { cu(self.inner.handle, flags) })
98 }
99
100 pub fn map(&self, stream: &Stream) -> Result<()> {
103 let d = driver()?;
104 let cu = d.cu_graphics_map_resources()?;
105 let mut arr = [self.inner.handle];
106 check(unsafe { cu(1, arr.as_mut_ptr(), stream.as_raw()) })
107 }
108
109 pub fn unmap(&self, stream: &Stream) -> Result<()> {
111 let d = driver()?;
112 let cu = d.cu_graphics_unmap_resources()?;
113 let mut arr = [self.inner.handle];
114 check(unsafe { cu(1, arr.as_mut_ptr(), stream.as_raw()) })
115 }
116
117 pub fn mapped_pointer(&self) -> Result<(CUdeviceptr, usize)> {
120 let d = driver()?;
121 let cu = d.cu_graphics_resource_get_mapped_pointer()?;
122 let mut dptr = CUdeviceptr(0);
123 let mut size: usize = 0;
124 check(unsafe { cu(&mut dptr, &mut size, self.inner.handle) })?;
125 Ok((dptr, size))
126 }
127
128 pub fn mapped_array(&self, array_index: u32, mip_level: u32) -> Result<CUarray> {
131 let d = driver()?;
132 let cu = d.cu_graphics_sub_resource_get_mapped_array()?;
133 let mut arr: CUarray = core::ptr::null_mut();
134 check(unsafe { cu(&mut arr, self.inner.handle, array_index, mip_level) })?;
135 Ok(arr)
136 }
137
138 pub fn mapped_mipmapped_array(&self) -> Result<CUmipmappedArray> {
140 let d = driver()?;
141 let cu = d.cu_graphics_resource_get_mapped_mipmapped_array()?;
142 let mut mip: CUmipmappedArray = core::ptr::null_mut();
143 check(unsafe { cu(&mut mip, self.inner.handle) })?;
144 Ok(mip)
145 }
146
147 pub fn map_all(resources: &[Self], stream: &Stream) -> Result<()> {
150 if resources.is_empty() {
151 return Ok(());
152 }
153 let d = driver()?;
154 let cu = d.cu_graphics_map_resources()?;
155 let mut raws: Vec<CUgraphicsResource> = resources.iter().map(|r| r.as_raw()).collect();
156 check(unsafe {
157 cu(
158 raws.len() as core::ffi::c_uint,
159 raws.as_mut_ptr(),
160 stream.as_raw(),
161 )
162 })
163 }
164
165 pub fn unmap_all(resources: &[Self], stream: &Stream) -> Result<()> {
167 if resources.is_empty() {
168 return Ok(());
169 }
170 let d = driver()?;
171 let cu = d.cu_graphics_unmap_resources()?;
172 let mut raws: Vec<CUgraphicsResource> = resources.iter().map(|r| r.as_raw()).collect();
173 check(unsafe {
174 cu(
175 raws.len() as core::ffi::c_uint,
176 raws.as_mut_ptr(),
177 stream.as_raw(),
178 )
179 })
180 }
181}
182
183impl Drop for GraphicsResourceInner {
184 fn drop(&mut self) {
185 if self.handle.is_null() {
186 return;
187 }
188 if let Ok(d) = driver() {
189 if let Ok(cu) = d.cu_graphics_unregister_resource() {
190 let _ = unsafe { cu(self.handle) };
191 }
192 }
193 }
194}
195
196pub mod gl {
198 use super::*;
199 use crate::device::Device;
200 use baracuda_cuda_sys::types::{GLenum, GLuint};
201
202 pub fn init() -> Result<()> {
205 let d = driver()?;
206 let cu = d.cu_gl_init()?;
207 check(unsafe { cu() })
208 }
209
210 pub fn get_devices(device_list: u32) -> Result<Vec<Device>> {
213 let d = driver()?;
214 let cu = d.cu_gl_get_devices()?;
215 let mut count: core::ffi::c_uint = 0;
217 let probe = unsafe { cu(&mut count, core::ptr::null_mut(), 0, device_list) };
218 if !probe.is_success() && probe != baracuda_cuda_sys::CUresult::ERROR_NOT_INITIALIZED {
222 check(probe)?;
223 }
224 if count == 0 {
225 return Ok(Vec::new());
226 }
227 let mut raw = vec![baracuda_cuda_sys::CUdevice(0); count as usize];
228 check(unsafe {
229 cu(
230 &mut count,
231 raw.as_mut_ptr(),
232 raw.len() as core::ffi::c_uint,
233 device_list,
234 )
235 })?;
236 Ok(raw.into_iter().map(Device).collect())
239 }
240
241 pub unsafe fn register_buffer(
250 context: &Context,
251 buffer: GLuint,
252 flags: u32,
253 ) -> Result<GraphicsResource> { unsafe {
254 context.set_current()?;
255 let d = driver()?;
256 let cu = d.cu_graphics_gl_register_buffer()?;
257 let mut resource: CUgraphicsResource = core::ptr::null_mut();
258 check(cu(&mut resource, buffer, flags))?;
259 Ok(GraphicsResource::from_raw(context, resource))
260 }}
261
262 pub unsafe fn register_image(
270 context: &Context,
271 image: GLuint,
272 target: GLenum,
273 flags: u32,
274 ) -> Result<GraphicsResource> { unsafe {
275 context.set_current()?;
276 let d = driver()?;
277 let cu = d.cu_graphics_gl_register_image()?;
278 let mut resource: CUgraphicsResource = core::ptr::null_mut();
279 check(cu(&mut resource, image, target, flags))?;
280 Ok(GraphicsResource::from_raw(context, resource))
281 }}
282}
283
284pub mod d3d9 {
286 use super::*;
287 use crate::device::Device;
288 use baracuda_cuda_sys::types::{ID3DDevice, ID3DResource};
289
290 pub unsafe fn get_device(adapter_name: *const core::ffi::c_char) -> Result<Device> { unsafe {
297 let d = driver()?;
298 let cu = d.cu_d3d9_get_device()?;
299 let mut dev = baracuda_cuda_sys::CUdevice(0);
300 check(cu(&mut dev, adapter_name))?;
301 Ok(Device(dev))
302 }}
303
304 pub unsafe fn get_devices(d3d_device: ID3DDevice, device_list: u32) -> Result<Vec<Device>> { unsafe {
310 let d = driver()?;
311 let cu = d.cu_d3d9_get_devices()?;
312 let mut count: core::ffi::c_uint = 0;
313 check(cu(
314 &mut count,
315 core::ptr::null_mut(),
316 0,
317 d3d_device,
318 device_list,
319 ))?;
320 if count == 0 {
321 return Ok(Vec::new());
322 }
323 let mut raw = vec![baracuda_cuda_sys::CUdevice(0); count as usize];
324 check(cu(
325 &mut count,
326 raw.as_mut_ptr(),
327 raw.len() as core::ffi::c_uint,
328 d3d_device,
329 device_list,
330 ))?;
331 Ok(raw.into_iter().map(Device).collect())
332 }}
333
334 pub unsafe fn register_resource(
341 context: &Context,
342 resource: ID3DResource,
343 flags: u32,
344 ) -> Result<GraphicsResource> { unsafe {
345 context.set_current()?;
346 let d = driver()?;
347 let cu = d.cu_graphics_d3d9_register_resource()?;
348 let mut res: CUgraphicsResource = core::ptr::null_mut();
349 check(cu(&mut res, resource, flags))?;
350 Ok(GraphicsResource::from_raw(context, res))
351 }}
352}
353
354pub mod d3d10 {
356 use super::*;
357 use crate::device::Device;
358 use baracuda_cuda_sys::types::{ID3DDevice, ID3DResource};
359
360 pub unsafe fn get_device(adapter: ID3DDevice) -> Result<Device> { unsafe {
364 let d = driver()?;
365 let cu = d.cu_d3d10_get_device()?;
366 let mut dev = baracuda_cuda_sys::CUdevice(0);
367 check(cu(&mut dev, adapter))?;
368 Ok(Device(dev))
369 }}
370
371 pub unsafe fn get_devices(d3d_device: ID3DDevice, device_list: u32) -> Result<Vec<Device>> { unsafe {
375 let d = driver()?;
376 let cu = d.cu_d3d10_get_devices()?;
377 let mut count: core::ffi::c_uint = 0;
378 check(cu(
379 &mut count,
380 core::ptr::null_mut(),
381 0,
382 d3d_device,
383 device_list,
384 ))?;
385 if count == 0 {
386 return Ok(Vec::new());
387 }
388 let mut raw = vec![baracuda_cuda_sys::CUdevice(0); count as usize];
389 check(cu(
390 &mut count,
391 raw.as_mut_ptr(),
392 raw.len() as core::ffi::c_uint,
393 d3d_device,
394 device_list,
395 ))?;
396 Ok(raw.into_iter().map(Device).collect())
397 }}
398
399 pub unsafe fn register_resource(
403 context: &Context,
404 resource: ID3DResource,
405 flags: u32,
406 ) -> Result<GraphicsResource> { unsafe {
407 context.set_current()?;
408 let d = driver()?;
409 let cu = d.cu_graphics_d3d10_register_resource()?;
410 let mut res: CUgraphicsResource = core::ptr::null_mut();
411 check(cu(&mut res, resource, flags))?;
412 Ok(GraphicsResource::from_raw(context, res))
413 }}
414}
415
416pub mod vdpau {
419 use super::*;
420 use crate::device::Device;
421 use baracuda_cuda_sys::types::{
422 VdpDevice, VdpGetProcAddress, VdpOutputSurface, VdpVideoSurface,
423 };
424
425 pub unsafe fn get_device(
432 vdp_device: VdpDevice,
433 vdp_get_proc_address: VdpGetProcAddress,
434 ) -> Result<Device> { unsafe {
435 let d = driver()?;
436 let cu = d.cu_vdpau_get_device()?;
437 let mut dev = baracuda_cuda_sys::CUdevice(0);
438 check(cu(&mut dev, vdp_device, vdp_get_proc_address))?;
439 Ok(Device(dev))
440 }}
441
442 pub unsafe fn register_video_surface(
450 context: &Context,
451 vdp_surface: VdpVideoSurface,
452 flags: u32,
453 ) -> Result<GraphicsResource> { unsafe {
454 context.set_current()?;
455 let d = driver()?;
456 let cu = d.cu_graphics_vdpau_register_video_surface()?;
457 let mut res: CUgraphicsResource = core::ptr::null_mut();
458 check(cu(&mut res, vdp_surface, flags))?;
459 Ok(GraphicsResource::from_raw(context, res))
460 }}
461
462 pub unsafe fn register_output_surface(
468 context: &Context,
469 vdp_surface: VdpOutputSurface,
470 flags: u32,
471 ) -> Result<GraphicsResource> { unsafe {
472 context.set_current()?;
473 let d = driver()?;
474 let cu = d.cu_graphics_vdpau_register_output_surface()?;
475 let mut res: CUgraphicsResource = core::ptr::null_mut();
476 check(cu(&mut res, vdp_surface, flags))?;
477 Ok(GraphicsResource::from_raw(context, res))
478 }}
479}
480
481pub mod egl {
484 use super::*;
485 use baracuda_cuda_sys::types::{CUeglFrame, EGLImageKHR, EGLStreamKHR, EGLSyncKHR};
486 use baracuda_cuda_sys::CUevent;
487 use core::ffi::c_void;
488
489 pub unsafe fn register_image(
496 context: &Context,
497 image: EGLImageKHR,
498 flags: u32,
499 ) -> Result<GraphicsResource> { unsafe {
500 context.set_current()?;
501 let d = driver()?;
502 let cu = d.cu_graphics_egl_register_image()?;
503 let mut res: CUgraphicsResource = core::ptr::null_mut();
504 check(cu(&mut res, image, flags))?;
505 Ok(GraphicsResource::from_raw(context, res))
506 }}
507
508 pub fn mapped_frame(
511 resource: &GraphicsResource,
512 index: u32,
513 mip_level: u32,
514 ) -> Result<CUeglFrame> {
515 let d = driver()?;
516 let cu = d.cu_graphics_resource_get_mapped_egl_frame()?;
517 let mut frame = CUeglFrame::default();
518 check(unsafe { cu(&mut frame, resource.as_raw(), index, mip_level) })?;
519 Ok(frame)
520 }
521
522 pub unsafe fn event_from_sync(egl_sync: EGLSyncKHR, flags: u32) -> Result<CUevent> { unsafe {
529 let d = driver()?;
530 let cu = d.cu_event_create_from_egl_sync()?;
531 let mut event: CUevent = core::ptr::null_mut();
532 check(cu(&mut event, egl_sync, flags))?;
533 Ok(event)
534 }}
535
536 pub unsafe fn stream_consumer_connect(
548 connection: *mut c_void,
549 stream: EGLStreamKHR,
550 ) -> Result<()> { unsafe {
551 let d = driver()?;
552 let cu = d.cu_egl_stream_consumer_connect()?;
553 check(cu(connection, stream))
554 }}
555
556 pub unsafe fn stream_consumer_disconnect(connection: *mut c_void) -> Result<()> { unsafe {
561 let d = driver()?;
562 let cu = d.cu_egl_stream_consumer_disconnect()?;
563 check(cu(connection))
564 }}
565
566 pub unsafe fn stream_consumer_acquire_frame(
574 context: &Context,
575 connection: *mut c_void,
576 cu_stream_out: *mut baracuda_cuda_sys::CUstream,
577 timeout: u32,
578 ) -> Result<GraphicsResource> { unsafe {
579 let d = driver()?;
580 let cu = d.cu_egl_stream_consumer_acquire_frame()?;
581 let mut resource: CUgraphicsResource = core::ptr::null_mut();
582 check(cu(connection, &mut resource, cu_stream_out, timeout))?;
583 Ok(GraphicsResource::from_raw(context, resource))
584 }}
585
586 pub unsafe fn stream_consumer_release_frame(
590 connection: *mut c_void,
591 resource: &GraphicsResource,
592 cu_stream_inout: *mut baracuda_cuda_sys::CUstream,
593 ) -> Result<()> { unsafe {
594 let d = driver()?;
595 let cu = d.cu_egl_stream_consumer_release_frame()?;
596 check(cu(connection, resource.as_raw(), cu_stream_inout))
597 }}
598
599 pub unsafe fn stream_producer_connect(
607 connection: *mut c_void,
608 stream: EGLStreamKHR,
609 width: i32,
610 height: i32,
611 ) -> Result<()> { unsafe {
612 let d = driver()?;
613 let cu = d.cu_egl_stream_producer_connect()?;
614 check(cu(connection, stream, width, height))
615 }}
616
617 pub unsafe fn stream_producer_disconnect(connection: *mut c_void) -> Result<()> { unsafe {
621 let d = driver()?;
622 let cu = d.cu_egl_stream_producer_disconnect()?;
623 check(cu(connection))
624 }}
625
626 pub unsafe fn stream_producer_present_frame(
634 connection: *mut c_void,
635 egl_frame: CUeglFrame,
636 cu_stream_inout: *mut baracuda_cuda_sys::CUstream,
637 ) -> Result<()> { unsafe {
638 let d = driver()?;
639 let cu = d.cu_egl_stream_producer_present_frame()?;
640 check(cu(connection, egl_frame, cu_stream_inout))
641 }}
642
643 pub unsafe fn stream_producer_return_frame(
650 connection: *mut c_void,
651 egl_frame: *mut CUeglFrame,
652 cu_stream_inout: *mut baracuda_cuda_sys::CUstream,
653 ) -> Result<()> { unsafe {
654 let d = driver()?;
655 let cu = d.cu_egl_stream_producer_return_frame()?;
656 check(cu(connection, egl_frame, cu_stream_inout))
657 }}
658}
659
660pub mod nvsci {
665 use super::*;
666 use crate::device::Device;
667 use baracuda_cuda_sys::types::NvSciSyncAttrList;
668
669 pub const SIGNAL: i32 = baracuda_cuda_sys::types::CUnvSciSyncAttr::SIGNAL;
671 pub const WAIT: i32 = baracuda_cuda_sys::types::CUnvSciSyncAttr::WAIT;
673
674 pub unsafe fn device_sync_attributes(
682 attr_list: NvSciSyncAttrList,
683 device: &Device,
684 direction: i32,
685 ) -> Result<()> { unsafe {
686 let d = driver()?;
687 let cu = d.cu_device_get_nv_sci_sync_attributes()?;
688 check(cu(attr_list, device.as_raw(), direction))
689 }}
690}
691
692pub mod d3d11 {
694 use super::*;
695 use crate::device::Device;
696 use baracuda_cuda_sys::types::{ID3DDevice, ID3DResource};
697
698 pub unsafe fn get_device(adapter: ID3DDevice) -> Result<Device> { unsafe {
702 let d = driver()?;
703 let cu = d.cu_d3d11_get_device()?;
704 let mut dev = baracuda_cuda_sys::CUdevice(0);
705 check(cu(&mut dev, adapter))?;
706 Ok(Device(dev))
707 }}
708
709 pub unsafe fn get_devices(d3d_device: ID3DDevice, device_list: u32) -> Result<Vec<Device>> { unsafe {
713 let d = driver()?;
714 let cu = d.cu_d3d11_get_devices()?;
715 let mut count: core::ffi::c_uint = 0;
716 check(cu(
717 &mut count,
718 core::ptr::null_mut(),
719 0,
720 d3d_device,
721 device_list,
722 ))?;
723 if count == 0 {
724 return Ok(Vec::new());
725 }
726 let mut raw = vec![baracuda_cuda_sys::CUdevice(0); count as usize];
727 check(cu(
728 &mut count,
729 raw.as_mut_ptr(),
730 raw.len() as core::ffi::c_uint,
731 d3d_device,
732 device_list,
733 ))?;
734 Ok(raw.into_iter().map(Device).collect())
735 }}
736
737 pub unsafe fn register_resource(
741 context: &Context,
742 resource: ID3DResource,
743 flags: u32,
744 ) -> Result<GraphicsResource> { unsafe {
745 context.set_current()?;
746 let d = driver()?;
747 let cu = d.cu_graphics_d3d11_register_resource()?;
748 let mut res: CUgraphicsResource = core::ptr::null_mut();
749 check(cu(&mut res, resource, flags))?;
750 Ok(GraphicsResource::from_raw(context, res))
751 }}
752}