1use std::sync::Arc;
24
25use baracuda_cuda_sys::CUgraphicsResource;
26use baracuda_cuda_sys::runtime::runtime;
27
28use crate::error::{Result, check};
29use crate::stream::Stream;
30
31pub use baracuda_cuda_sys::types::{
32 CUgraphicsMapResourceFlags as MapResourceFlags, CUgraphicsRegisterFlags as RegisterFlags,
33};
34
35#[derive(Clone)]
37pub struct GraphicsResource {
38 inner: Arc<GraphicsResourceInner>,
39}
40
41struct GraphicsResourceInner {
42 handle: CUgraphicsResource,
43}
44
45unsafe impl Send for GraphicsResourceInner {}
46unsafe impl Sync for GraphicsResourceInner {}
47
48impl core::fmt::Debug for GraphicsResourceInner {
49 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
50 f.debug_struct("GraphicsResource")
51 .field("handle", &self.handle)
52 .finish_non_exhaustive()
53 }
54}
55
56impl core::fmt::Debug for GraphicsResource {
57 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
58 self.inner.fmt(f)
59 }
60}
61
62impl GraphicsResource {
63 pub unsafe fn from_raw(handle: CUgraphicsResource) -> Self {
70 Self {
71 inner: Arc::new(GraphicsResourceInner { handle }),
72 }
73 }
74
75 #[inline]
77 pub fn as_raw(&self) -> CUgraphicsResource {
78 self.inner.handle
79 }
80
81 pub fn set_map_flags(&self, flags: u32) -> Result<()> {
83 let r = runtime()?;
84 let cu = r.cuda_graphics_resource_set_map_flags()?;
85 check(unsafe { cu(self.inner.handle, flags) })
86 }
87
88 pub fn map(&self, stream: &Stream) -> Result<()> {
90 let r = runtime()?;
91 let cu = r.cuda_graphics_map_resources()?;
92 let mut arr = [self.inner.handle];
93 check(unsafe { cu(1, arr.as_mut_ptr(), stream.as_raw()) })
94 }
95
96 pub fn unmap(&self, stream: &Stream) -> Result<()> {
98 let r = runtime()?;
99 let cu = r.cuda_graphics_unmap_resources()?;
100 let mut arr = [self.inner.handle];
101 check(unsafe { cu(1, arr.as_mut_ptr(), stream.as_raw()) })
102 }
103
104 pub fn mapped_pointer(&self) -> Result<(*mut core::ffi::c_void, usize)> {
106 let r = runtime()?;
107 let cu = r.cuda_graphics_resource_get_mapped_pointer()?;
108 let mut dptr: *mut core::ffi::c_void = core::ptr::null_mut();
109 let mut size: usize = 0;
110 check(unsafe { cu(&mut dptr, &mut size, self.inner.handle) })?;
111 Ok((dptr, size))
112 }
113
114 pub fn mapped_array(&self, array_index: u32, mip_level: u32) -> Result<*mut core::ffi::c_void> {
116 let r = runtime()?;
117 let cu = r.cuda_graphics_sub_resource_get_mapped_array()?;
118 let mut arr: *mut core::ffi::c_void = core::ptr::null_mut();
119 check(unsafe { cu(&mut arr, self.inner.handle, array_index, mip_level) })?;
120 Ok(arr)
121 }
122
123 pub fn mapped_mipmapped_array(&self) -> Result<*mut core::ffi::c_void> {
125 let r = runtime()?;
126 let cu = r.cuda_graphics_resource_get_mapped_mipmapped_array()?;
127 let mut mip: *mut core::ffi::c_void = core::ptr::null_mut();
128 check(unsafe { cu(&mut mip, self.inner.handle) })?;
129 Ok(mip)
130 }
131
132 pub fn map_all(resources: &[Self], stream: &Stream) -> Result<()> {
134 if resources.is_empty() {
135 return Ok(());
136 }
137 let r = runtime()?;
138 let cu = r.cuda_graphics_map_resources()?;
139 let mut raws: Vec<CUgraphicsResource> = resources.iter().map(|x| x.as_raw()).collect();
140 check(unsafe {
141 cu(
142 raws.len() as core::ffi::c_int,
143 raws.as_mut_ptr(),
144 stream.as_raw(),
145 )
146 })
147 }
148
149 pub fn unmap_all(resources: &[Self], stream: &Stream) -> Result<()> {
151 if resources.is_empty() {
152 return Ok(());
153 }
154 let r = runtime()?;
155 let cu = r.cuda_graphics_unmap_resources()?;
156 let mut raws: Vec<CUgraphicsResource> = resources.iter().map(|x| x.as_raw()).collect();
157 check(unsafe {
158 cu(
159 raws.len() as core::ffi::c_int,
160 raws.as_mut_ptr(),
161 stream.as_raw(),
162 )
163 })
164 }
165}
166
167impl Drop for GraphicsResourceInner {
168 fn drop(&mut self) {
169 if self.handle.is_null() {
170 return;
171 }
172 if let Ok(r) = runtime() {
173 if let Ok(cu) = r.cuda_graphics_unregister_resource() {
174 let _ = unsafe { cu(self.handle) };
175 }
176 }
177 }
178}
179
180pub mod gl {
182 use super::*;
183 use baracuda_cuda_sys::types::{GLenum, GLuint};
184
185 pub fn get_devices(device_list: u32) -> Result<Vec<i32>> {
189 let r = runtime()?;
190 let cu = r.cuda_gl_get_devices()?;
191 let mut count: core::ffi::c_uint = 0;
192 let probe_rc = unsafe { cu(&mut count, core::ptr::null_mut(), 0, device_list) };
193 if probe_rc != baracuda_cuda_sys::runtime::cudaError_t::Success {
195 return Ok(Vec::new());
196 }
197 if count == 0 {
198 return Ok(Vec::new());
199 }
200 let mut out = vec![0i32; count as usize];
201 check(unsafe {
202 cu(
203 &mut count,
204 out.as_mut_ptr(),
205 out.len() as core::ffi::c_uint,
206 device_list,
207 )
208 })?;
209 out.truncate(count as usize);
210 Ok(out)
211 }
212
213 pub unsafe fn register_buffer(buffer: GLuint, flags: u32) -> Result<GraphicsResource> {
220 unsafe {
221 let r = runtime()?;
222 let cu = r.cuda_graphics_gl_register_buffer()?;
223 let mut res: CUgraphicsResource = core::ptr::null_mut();
224 check(cu(&mut res, buffer, flags))?;
225 Ok(GraphicsResource::from_raw(res))
226 }
227 }
228
229 pub unsafe fn register_image(
236 image: GLuint,
237 target: GLenum,
238 flags: u32,
239 ) -> Result<GraphicsResource> {
240 unsafe {
241 let r = runtime()?;
242 let cu = r.cuda_graphics_gl_register_image()?;
243 let mut res: CUgraphicsResource = core::ptr::null_mut();
244 check(cu(&mut res, image, target, flags))?;
245 Ok(GraphicsResource::from_raw(res))
246 }
247 }
248}
249
250pub mod d3d9 {
252 use super::*;
253
254 pub unsafe fn get_device(adapter_name: *const core::ffi::c_char) -> Result<i32> {
261 unsafe {
262 let r = runtime()?;
263 let cu = r.cuda_d3d9_get_device()?;
264 let mut dev: core::ffi::c_int = 0;
265 check(cu(&mut dev, adapter_name))?;
266 Ok(dev)
267 }
268 }
269
270 pub unsafe fn get_devices(
276 d3d_device: *mut core::ffi::c_void,
277 device_list: u32,
278 ) -> Result<Vec<i32>> {
279 unsafe {
280 let r = runtime()?;
281 let cu = r.cuda_d3d9_get_devices()?;
282 let mut count: core::ffi::c_uint = 0;
283 check(cu(
284 &mut count,
285 core::ptr::null_mut(),
286 0,
287 d3d_device,
288 device_list,
289 ))?;
290 if count == 0 {
291 return Ok(Vec::new());
292 }
293 let mut out = vec![0i32; count as usize];
294 check(cu(
295 &mut count,
296 out.as_mut_ptr(),
297 out.len() as core::ffi::c_uint,
298 d3d_device,
299 device_list,
300 ))?;
301 out.truncate(count as usize);
302 Ok(out)
303 }
304 }
305
306 pub unsafe fn register_resource(
312 resource: *mut core::ffi::c_void,
313 flags: u32,
314 ) -> Result<GraphicsResource> {
315 unsafe {
316 let r = runtime()?;
317 let cu = r.cuda_graphics_d3d9_register_resource()?;
318 let mut res: CUgraphicsResource = core::ptr::null_mut();
319 check(cu(&mut res, resource, flags))?;
320 Ok(GraphicsResource::from_raw(res))
321 }
322 }
323}
324
325pub mod d3d10 {
327 use super::*;
328
329 pub unsafe fn get_device(adapter: *mut core::ffi::c_void) -> Result<i32> {
333 unsafe {
334 let r = runtime()?;
335 let cu = r.cuda_d3d10_get_device()?;
336 let mut dev: core::ffi::c_int = 0;
337 check(cu(&mut dev, adapter))?;
338 Ok(dev)
339 }
340 }
341
342 pub unsafe fn get_devices(
346 d3d_device: *mut core::ffi::c_void,
347 device_list: u32,
348 ) -> Result<Vec<i32>> {
349 unsafe {
350 let r = runtime()?;
351 let cu = r.cuda_d3d10_get_devices()?;
352 let mut count: core::ffi::c_uint = 0;
353 check(cu(
354 &mut count,
355 core::ptr::null_mut(),
356 0,
357 d3d_device,
358 device_list,
359 ))?;
360 if count == 0 {
361 return Ok(Vec::new());
362 }
363 let mut out = vec![0i32; count as usize];
364 check(cu(
365 &mut count,
366 out.as_mut_ptr(),
367 out.len() as core::ffi::c_uint,
368 d3d_device,
369 device_list,
370 ))?;
371 out.truncate(count as usize);
372 Ok(out)
373 }
374 }
375
376 pub unsafe fn register_resource(
380 resource: *mut core::ffi::c_void,
381 flags: u32,
382 ) -> Result<GraphicsResource> {
383 unsafe {
384 let r = runtime()?;
385 let cu = r.cuda_graphics_d3d10_register_resource()?;
386 let mut res: CUgraphicsResource = core::ptr::null_mut();
387 check(cu(&mut res, resource, flags))?;
388 Ok(GraphicsResource::from_raw(res))
389 }
390 }
391}
392
393pub mod d3d11 {
395 use super::*;
396
397 pub unsafe fn get_device(adapter: *mut core::ffi::c_void) -> Result<i32> {
401 unsafe {
402 let r = runtime()?;
403 let cu = r.cuda_d3d11_get_device()?;
404 let mut dev: core::ffi::c_int = 0;
405 check(cu(&mut dev, adapter))?;
406 Ok(dev)
407 }
408 }
409
410 pub unsafe fn get_devices(
414 d3d_device: *mut core::ffi::c_void,
415 device_list: u32,
416 ) -> Result<Vec<i32>> {
417 unsafe {
418 let r = runtime()?;
419 let cu = r.cuda_d3d11_get_devices()?;
420 let mut count: core::ffi::c_uint = 0;
421 check(cu(
422 &mut count,
423 core::ptr::null_mut(),
424 0,
425 d3d_device,
426 device_list,
427 ))?;
428 if count == 0 {
429 return Ok(Vec::new());
430 }
431 let mut out = vec![0i32; count as usize];
432 check(cu(
433 &mut count,
434 out.as_mut_ptr(),
435 out.len() as core::ffi::c_uint,
436 d3d_device,
437 device_list,
438 ))?;
439 out.truncate(count as usize);
440 Ok(out)
441 }
442 }
443
444 pub unsafe fn register_resource(
448 resource: *mut core::ffi::c_void,
449 flags: u32,
450 ) -> Result<GraphicsResource> {
451 unsafe {
452 let r = runtime()?;
453 let cu = r.cuda_graphics_d3d11_register_resource()?;
454 let mut res: CUgraphicsResource = core::ptr::null_mut();
455 check(cu(&mut res, resource, flags))?;
456 Ok(GraphicsResource::from_raw(res))
457 }
458 }
459}
460
461pub mod vdpau {
463 use super::*;
464
465 pub unsafe fn get_device(
470 vdp_device: *mut core::ffi::c_void,
471 vdp_get_proc_address: *mut core::ffi::c_void,
472 ) -> Result<i32> {
473 unsafe {
474 let r = runtime()?;
475 let cu = r.cuda_vdpau_get_device()?;
476 let mut dev: core::ffi::c_int = 0;
477 check(cu(&mut dev, vdp_device, vdp_get_proc_address))?;
478 Ok(dev)
479 }
480 }
481
482 pub unsafe fn register_video_surface(
489 vdp_surface: *mut core::ffi::c_void,
490 flags: u32,
491 ) -> Result<GraphicsResource> {
492 unsafe {
493 let r = runtime()?;
494 let cu = r.cuda_graphics_vdpau_register_video_surface()?;
495 let mut res: CUgraphicsResource = core::ptr::null_mut();
496 check(cu(&mut res, vdp_surface, flags))?;
497 Ok(GraphicsResource::from_raw(res))
498 }
499 }
500
501 pub unsafe fn register_output_surface(
507 vdp_surface: *mut core::ffi::c_void,
508 flags: u32,
509 ) -> Result<GraphicsResource> {
510 unsafe {
511 let r = runtime()?;
512 let cu = r.cuda_graphics_vdpau_register_output_surface()?;
513 let mut res: CUgraphicsResource = core::ptr::null_mut();
514 check(cu(&mut res, vdp_surface, flags))?;
515 Ok(GraphicsResource::from_raw(res))
516 }
517 }
518}
519
520pub mod egl {
522 use super::*;
523 use baracuda_cuda_sys::runtime::cudaEvent_t;
524 use core::ffi::c_void;
525
526 pub unsafe fn register_image(image: *mut c_void, flags: u32) -> Result<GraphicsResource> {
532 unsafe {
533 let r = runtime()?;
534 let cu = r.cuda_graphics_egl_register_image()?;
535 let mut res: CUgraphicsResource = core::ptr::null_mut();
536 check(cu(&mut res, image, flags))?;
537 Ok(GraphicsResource::from_raw(res))
538 }
539 }
540
541 pub unsafe fn mapped_frame(
548 resource: &GraphicsResource,
549 egl_frame_out: *mut c_void,
550 index: u32,
551 mip_level: u32,
552 ) -> Result<()> {
553 unsafe {
554 let r = runtime()?;
555 let cu = r.cuda_graphics_resource_get_mapped_egl_frame()?;
556 check(cu(egl_frame_out, resource.as_raw(), index, mip_level))
557 }
558 }
559
560 pub unsafe fn event_from_sync(egl_sync: *mut c_void, flags: u32) -> Result<cudaEvent_t> {
566 unsafe {
567 let r = runtime()?;
568 let cu = r.cuda_event_create_from_egl_sync()?;
569 let mut event: cudaEvent_t = core::ptr::null_mut();
570 check(cu(&mut event, egl_sync, flags))?;
571 Ok(event)
572 }
573 }
574
575 pub unsafe fn stream_consumer_connect(
582 connection: *mut c_void,
583 egl_stream: *mut c_void,
584 ) -> Result<()> {
585 unsafe {
586 let r = runtime()?;
587 let cu = r.cuda_egl_stream_consumer_connect()?;
588 check(cu(connection, egl_stream))
589 }
590 }
591
592 pub unsafe fn stream_consumer_disconnect(connection: *mut c_void) -> Result<()> {
596 unsafe {
597 let r = runtime()?;
598 let cu = r.cuda_egl_stream_consumer_disconnect()?;
599 check(cu(connection))
600 }
601 }
602
603 pub unsafe fn stream_consumer_acquire_frame(
608 connection: *mut c_void,
609 stream_out: *mut baracuda_cuda_sys::runtime::cudaStream_t,
610 timeout: u32,
611 ) -> Result<GraphicsResource> {
612 unsafe {
613 let r = runtime()?;
614 let cu = r.cuda_egl_stream_consumer_acquire_frame()?;
615 let mut res: CUgraphicsResource = core::ptr::null_mut();
616 check(cu(connection, &mut res, stream_out, timeout))?;
617 Ok(GraphicsResource::from_raw(res))
618 }
619 }
620
621 pub unsafe fn stream_consumer_release_frame(
625 connection: *mut c_void,
626 resource: &GraphicsResource,
627 stream_inout: *mut baracuda_cuda_sys::runtime::cudaStream_t,
628 ) -> Result<()> {
629 unsafe {
630 let r = runtime()?;
631 let cu = r.cuda_egl_stream_consumer_release_frame()?;
632 check(cu(connection, resource.as_raw(), stream_inout))
633 }
634 }
635
636 pub unsafe fn stream_producer_connect(
642 connection: *mut c_void,
643 egl_stream: *mut c_void,
644 width: i32,
645 height: i32,
646 ) -> Result<()> {
647 unsafe {
648 let r = runtime()?;
649 let cu = r.cuda_egl_stream_producer_connect()?;
650 check(cu(connection, egl_stream, width, height))
651 }
652 }
653
654 pub unsafe fn stream_producer_disconnect(connection: *mut c_void) -> Result<()> {
658 unsafe {
659 let r = runtime()?;
660 let cu = r.cuda_egl_stream_producer_disconnect()?;
661 check(cu(connection))
662 }
663 }
664
665 pub unsafe fn stream_producer_present_frame(
671 connection: *mut c_void,
672 egl_frame: *mut c_void,
673 stream_inout: *mut baracuda_cuda_sys::runtime::cudaStream_t,
674 ) -> Result<()> {
675 unsafe {
676 let r = runtime()?;
677 let cu = r.cuda_egl_stream_producer_present_frame()?;
678 check(cu(connection, egl_frame, stream_inout))
679 }
680 }
681
682 pub unsafe fn stream_producer_return_frame(
688 connection: *mut c_void,
689 egl_frame_out: *mut c_void,
690 stream_inout: *mut baracuda_cuda_sys::runtime::cudaStream_t,
691 ) -> Result<()> {
692 unsafe {
693 let r = runtime()?;
694 let cu = r.cuda_egl_stream_producer_return_frame()?;
695 check(cu(connection, egl_frame_out, stream_inout))
696 }
697 }
698}
699
700pub mod nvsci {
707 use super::*;
708 use crate::device::Device;
709
710 pub const SIGNAL: i32 = 0;
712 pub const WAIT: i32 = 1;
714
715 pub unsafe fn device_sync_attributes(
722 attr_list: *mut core::ffi::c_void,
723 device: &Device,
724 direction: i32,
725 ) -> Result<()> {
726 unsafe {
727 let r = runtime()?;
728 let cu = r.cuda_device_get_nv_sci_sync_attributes()?;
729 check(cu(attr_list, device.ordinal(), direction))
730 }
731 }
732}