1use std::sync::Arc;
24
25use baracuda_cuda_sys::runtime::runtime;
26use baracuda_cuda_sys::CUgraphicsResource;
27
28use crate::error::{check, Result};
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]
76 pub fn as_raw(&self) -> CUgraphicsResource {
77 self.inner.handle
78 }
79
80 pub fn set_map_flags(&self, flags: u32) -> Result<()> {
82 let r = runtime()?;
83 let cu = r.cuda_graphics_resource_set_map_flags()?;
84 check(unsafe { cu(self.inner.handle, flags) })
85 }
86
87 pub fn map(&self, stream: &Stream) -> Result<()> {
89 let r = runtime()?;
90 let cu = r.cuda_graphics_map_resources()?;
91 let mut arr = [self.inner.handle];
92 check(unsafe { cu(1, arr.as_mut_ptr(), stream.as_raw()) })
93 }
94
95 pub fn unmap(&self, stream: &Stream) -> Result<()> {
97 let r = runtime()?;
98 let cu = r.cuda_graphics_unmap_resources()?;
99 let mut arr = [self.inner.handle];
100 check(unsafe { cu(1, arr.as_mut_ptr(), stream.as_raw()) })
101 }
102
103 pub fn mapped_pointer(&self) -> Result<(*mut core::ffi::c_void, usize)> {
105 let r = runtime()?;
106 let cu = r.cuda_graphics_resource_get_mapped_pointer()?;
107 let mut dptr: *mut core::ffi::c_void = core::ptr::null_mut();
108 let mut size: usize = 0;
109 check(unsafe { cu(&mut dptr, &mut size, self.inner.handle) })?;
110 Ok((dptr, size))
111 }
112
113 pub fn mapped_array(&self, array_index: u32, mip_level: u32) -> Result<*mut core::ffi::c_void> {
115 let r = runtime()?;
116 let cu = r.cuda_graphics_sub_resource_get_mapped_array()?;
117 let mut arr: *mut core::ffi::c_void = core::ptr::null_mut();
118 check(unsafe { cu(&mut arr, self.inner.handle, array_index, mip_level) })?;
119 Ok(arr)
120 }
121
122 pub fn mapped_mipmapped_array(&self) -> Result<*mut core::ffi::c_void> {
124 let r = runtime()?;
125 let cu = r.cuda_graphics_resource_get_mapped_mipmapped_array()?;
126 let mut mip: *mut core::ffi::c_void = core::ptr::null_mut();
127 check(unsafe { cu(&mut mip, self.inner.handle) })?;
128 Ok(mip)
129 }
130
131 pub fn map_all(resources: &[Self], stream: &Stream) -> Result<()> {
133 if resources.is_empty() {
134 return Ok(());
135 }
136 let r = runtime()?;
137 let cu = r.cuda_graphics_map_resources()?;
138 let mut raws: Vec<CUgraphicsResource> = resources.iter().map(|x| x.as_raw()).collect();
139 check(unsafe {
140 cu(
141 raws.len() as core::ffi::c_int,
142 raws.as_mut_ptr(),
143 stream.as_raw(),
144 )
145 })
146 }
147
148 pub fn unmap_all(resources: &[Self], stream: &Stream) -> Result<()> {
150 if resources.is_empty() {
151 return Ok(());
152 }
153 let r = runtime()?;
154 let cu = r.cuda_graphics_unmap_resources()?;
155 let mut raws: Vec<CUgraphicsResource> = resources.iter().map(|x| x.as_raw()).collect();
156 check(unsafe {
157 cu(
158 raws.len() as core::ffi::c_int,
159 raws.as_mut_ptr(),
160 stream.as_raw(),
161 )
162 })
163 }
164}
165
166impl Drop for GraphicsResourceInner {
167 fn drop(&mut self) {
168 if self.handle.is_null() {
169 return;
170 }
171 if let Ok(r) = runtime() {
172 if let Ok(cu) = r.cuda_graphics_unregister_resource() {
173 let _ = unsafe { cu(self.handle) };
174 }
175 }
176 }
177}
178
179pub mod gl {
181 use super::*;
182 use baracuda_cuda_sys::types::{GLenum, GLuint};
183
184 pub fn get_devices(device_list: u32) -> Result<Vec<i32>> {
188 let r = runtime()?;
189 let cu = r.cuda_gl_get_devices()?;
190 let mut count: core::ffi::c_uint = 0;
191 let probe_rc = unsafe { cu(&mut count, core::ptr::null_mut(), 0, device_list) };
192 if probe_rc != baracuda_cuda_sys::runtime::cudaError_t::Success {
194 return Ok(Vec::new());
195 }
196 if count == 0 {
197 return Ok(Vec::new());
198 }
199 let mut out = vec![0i32; count as usize];
200 check(unsafe {
201 cu(
202 &mut count,
203 out.as_mut_ptr(),
204 out.len() as core::ffi::c_uint,
205 device_list,
206 )
207 })?;
208 out.truncate(count as usize);
209 Ok(out)
210 }
211
212 pub unsafe fn register_buffer(buffer: GLuint, flags: u32) -> Result<GraphicsResource> { unsafe {
219 let r = runtime()?;
220 let cu = r.cuda_graphics_gl_register_buffer()?;
221 let mut res: CUgraphicsResource = core::ptr::null_mut();
222 check(cu(&mut res, buffer, flags))?;
223 Ok(GraphicsResource::from_raw(res))
224 }}
225
226 pub unsafe fn register_image(
233 image: GLuint,
234 target: GLenum,
235 flags: u32,
236 ) -> Result<GraphicsResource> { unsafe {
237 let r = runtime()?;
238 let cu = r.cuda_graphics_gl_register_image()?;
239 let mut res: CUgraphicsResource = core::ptr::null_mut();
240 check(cu(&mut res, image, target, flags))?;
241 Ok(GraphicsResource::from_raw(res))
242 }}
243}
244
245pub mod d3d9 {
247 use super::*;
248
249 pub unsafe fn get_device(adapter_name: *const core::ffi::c_char) -> Result<i32> { unsafe {
256 let r = runtime()?;
257 let cu = r.cuda_d3d9_get_device()?;
258 let mut dev: core::ffi::c_int = 0;
259 check(cu(&mut dev, adapter_name))?;
260 Ok(dev)
261 }}
262
263 pub unsafe fn get_devices(
269 d3d_device: *mut core::ffi::c_void,
270 device_list: u32,
271 ) -> Result<Vec<i32>> { unsafe {
272 let r = runtime()?;
273 let cu = r.cuda_d3d9_get_devices()?;
274 let mut count: core::ffi::c_uint = 0;
275 check(cu(
276 &mut count,
277 core::ptr::null_mut(),
278 0,
279 d3d_device,
280 device_list,
281 ))?;
282 if count == 0 {
283 return Ok(Vec::new());
284 }
285 let mut out = vec![0i32; count as usize];
286 check(cu(
287 &mut count,
288 out.as_mut_ptr(),
289 out.len() as core::ffi::c_uint,
290 d3d_device,
291 device_list,
292 ))?;
293 out.truncate(count as usize);
294 Ok(out)
295 }}
296
297 pub unsafe fn register_resource(
303 resource: *mut core::ffi::c_void,
304 flags: u32,
305 ) -> Result<GraphicsResource> { unsafe {
306 let r = runtime()?;
307 let cu = r.cuda_graphics_d3d9_register_resource()?;
308 let mut res: CUgraphicsResource = core::ptr::null_mut();
309 check(cu(&mut res, resource, flags))?;
310 Ok(GraphicsResource::from_raw(res))
311 }}
312}
313
314pub mod d3d10 {
316 use super::*;
317
318 pub unsafe fn get_device(adapter: *mut core::ffi::c_void) -> Result<i32> { unsafe {
322 let r = runtime()?;
323 let cu = r.cuda_d3d10_get_device()?;
324 let mut dev: core::ffi::c_int = 0;
325 check(cu(&mut dev, adapter))?;
326 Ok(dev)
327 }}
328
329 pub unsafe fn get_devices(
333 d3d_device: *mut core::ffi::c_void,
334 device_list: u32,
335 ) -> Result<Vec<i32>> { unsafe {
336 let r = runtime()?;
337 let cu = r.cuda_d3d10_get_devices()?;
338 let mut count: core::ffi::c_uint = 0;
339 check(cu(
340 &mut count,
341 core::ptr::null_mut(),
342 0,
343 d3d_device,
344 device_list,
345 ))?;
346 if count == 0 {
347 return Ok(Vec::new());
348 }
349 let mut out = vec![0i32; count as usize];
350 check(cu(
351 &mut count,
352 out.as_mut_ptr(),
353 out.len() as core::ffi::c_uint,
354 d3d_device,
355 device_list,
356 ))?;
357 out.truncate(count as usize);
358 Ok(out)
359 }}
360
361 pub unsafe fn register_resource(
365 resource: *mut core::ffi::c_void,
366 flags: u32,
367 ) -> Result<GraphicsResource> { unsafe {
368 let r = runtime()?;
369 let cu = r.cuda_graphics_d3d10_register_resource()?;
370 let mut res: CUgraphicsResource = core::ptr::null_mut();
371 check(cu(&mut res, resource, flags))?;
372 Ok(GraphicsResource::from_raw(res))
373 }}
374}
375
376pub mod d3d11 {
378 use super::*;
379
380 pub unsafe fn get_device(adapter: *mut core::ffi::c_void) -> Result<i32> { unsafe {
384 let r = runtime()?;
385 let cu = r.cuda_d3d11_get_device()?;
386 let mut dev: core::ffi::c_int = 0;
387 check(cu(&mut dev, adapter))?;
388 Ok(dev)
389 }}
390
391 pub unsafe fn get_devices(
395 d3d_device: *mut core::ffi::c_void,
396 device_list: u32,
397 ) -> Result<Vec<i32>> { unsafe {
398 let r = runtime()?;
399 let cu = r.cuda_d3d11_get_devices()?;
400 let mut count: core::ffi::c_uint = 0;
401 check(cu(
402 &mut count,
403 core::ptr::null_mut(),
404 0,
405 d3d_device,
406 device_list,
407 ))?;
408 if count == 0 {
409 return Ok(Vec::new());
410 }
411 let mut out = vec![0i32; count as usize];
412 check(cu(
413 &mut count,
414 out.as_mut_ptr(),
415 out.len() as core::ffi::c_uint,
416 d3d_device,
417 device_list,
418 ))?;
419 out.truncate(count as usize);
420 Ok(out)
421 }}
422
423 pub unsafe fn register_resource(
427 resource: *mut core::ffi::c_void,
428 flags: u32,
429 ) -> Result<GraphicsResource> { unsafe {
430 let r = runtime()?;
431 let cu = r.cuda_graphics_d3d11_register_resource()?;
432 let mut res: CUgraphicsResource = core::ptr::null_mut();
433 check(cu(&mut res, resource, flags))?;
434 Ok(GraphicsResource::from_raw(res))
435 }}
436}
437
438pub mod vdpau {
440 use super::*;
441
442 pub unsafe fn get_device(
447 vdp_device: *mut core::ffi::c_void,
448 vdp_get_proc_address: *mut core::ffi::c_void,
449 ) -> Result<i32> { unsafe {
450 let r = runtime()?;
451 let cu = r.cuda_vdpau_get_device()?;
452 let mut dev: core::ffi::c_int = 0;
453 check(cu(&mut dev, vdp_device, vdp_get_proc_address))?;
454 Ok(dev)
455 }}
456
457 pub unsafe fn register_video_surface(
464 vdp_surface: *mut core::ffi::c_void,
465 flags: u32,
466 ) -> Result<GraphicsResource> { unsafe {
467 let r = runtime()?;
468 let cu = r.cuda_graphics_vdpau_register_video_surface()?;
469 let mut res: CUgraphicsResource = core::ptr::null_mut();
470 check(cu(&mut res, vdp_surface, flags))?;
471 Ok(GraphicsResource::from_raw(res))
472 }}
473
474 pub unsafe fn register_output_surface(
480 vdp_surface: *mut core::ffi::c_void,
481 flags: u32,
482 ) -> Result<GraphicsResource> { unsafe {
483 let r = runtime()?;
484 let cu = r.cuda_graphics_vdpau_register_output_surface()?;
485 let mut res: CUgraphicsResource = core::ptr::null_mut();
486 check(cu(&mut res, vdp_surface, flags))?;
487 Ok(GraphicsResource::from_raw(res))
488 }}
489}
490
491pub mod egl {
493 use super::*;
494 use baracuda_cuda_sys::runtime::cudaEvent_t;
495 use core::ffi::c_void;
496
497 pub unsafe fn register_image(image: *mut c_void, flags: u32) -> Result<GraphicsResource> { unsafe {
503 let r = runtime()?;
504 let cu = r.cuda_graphics_egl_register_image()?;
505 let mut res: CUgraphicsResource = core::ptr::null_mut();
506 check(cu(&mut res, image, flags))?;
507 Ok(GraphicsResource::from_raw(res))
508 }}
509
510 pub unsafe fn mapped_frame(
517 resource: &GraphicsResource,
518 egl_frame_out: *mut c_void,
519 index: u32,
520 mip_level: u32,
521 ) -> Result<()> { unsafe {
522 let r = runtime()?;
523 let cu = r.cuda_graphics_resource_get_mapped_egl_frame()?;
524 check(cu(egl_frame_out, resource.as_raw(), index, mip_level))
525 }}
526
527 pub unsafe fn event_from_sync(egl_sync: *mut c_void, flags: u32) -> Result<cudaEvent_t> { unsafe {
533 let r = runtime()?;
534 let cu = r.cuda_event_create_from_egl_sync()?;
535 let mut event: cudaEvent_t = core::ptr::null_mut();
536 check(cu(&mut event, egl_sync, flags))?;
537 Ok(event)
538 }}
539
540 pub unsafe fn stream_consumer_connect(
547 connection: *mut c_void,
548 egl_stream: *mut c_void,
549 ) -> Result<()> { unsafe {
550 let r = runtime()?;
551 let cu = r.cuda_egl_stream_consumer_connect()?;
552 check(cu(connection, egl_stream))
553 }}
554
555 pub unsafe fn stream_consumer_disconnect(connection: *mut c_void) -> Result<()> { unsafe {
559 let r = runtime()?;
560 let cu = r.cuda_egl_stream_consumer_disconnect()?;
561 check(cu(connection))
562 }}
563
564 pub unsafe fn stream_consumer_acquire_frame(
569 connection: *mut c_void,
570 stream_out: *mut baracuda_cuda_sys::runtime::cudaStream_t,
571 timeout: u32,
572 ) -> Result<GraphicsResource> { unsafe {
573 let r = runtime()?;
574 let cu = r.cuda_egl_stream_consumer_acquire_frame()?;
575 let mut res: CUgraphicsResource = core::ptr::null_mut();
576 check(cu(connection, &mut res, stream_out, timeout))?;
577 Ok(GraphicsResource::from_raw(res))
578 }}
579
580 pub unsafe fn stream_consumer_release_frame(
584 connection: *mut c_void,
585 resource: &GraphicsResource,
586 stream_inout: *mut baracuda_cuda_sys::runtime::cudaStream_t,
587 ) -> Result<()> { unsafe {
588 let r = runtime()?;
589 let cu = r.cuda_egl_stream_consumer_release_frame()?;
590 check(cu(connection, resource.as_raw(), stream_inout))
591 }}
592
593 pub unsafe fn stream_producer_connect(
599 connection: *mut c_void,
600 egl_stream: *mut c_void,
601 width: i32,
602 height: i32,
603 ) -> Result<()> { unsafe {
604 let r = runtime()?;
605 let cu = r.cuda_egl_stream_producer_connect()?;
606 check(cu(connection, egl_stream, width, height))
607 }}
608
609 pub unsafe fn stream_producer_disconnect(connection: *mut c_void) -> Result<()> { unsafe {
613 let r = runtime()?;
614 let cu = r.cuda_egl_stream_producer_disconnect()?;
615 check(cu(connection))
616 }}
617
618 pub unsafe fn stream_producer_present_frame(
624 connection: *mut c_void,
625 egl_frame: *mut c_void,
626 stream_inout: *mut baracuda_cuda_sys::runtime::cudaStream_t,
627 ) -> Result<()> { unsafe {
628 let r = runtime()?;
629 let cu = r.cuda_egl_stream_producer_present_frame()?;
630 check(cu(connection, egl_frame, stream_inout))
631 }}
632
633 pub unsafe fn stream_producer_return_frame(
639 connection: *mut c_void,
640 egl_frame_out: *mut c_void,
641 stream_inout: *mut baracuda_cuda_sys::runtime::cudaStream_t,
642 ) -> Result<()> { unsafe {
643 let r = runtime()?;
644 let cu = r.cuda_egl_stream_producer_return_frame()?;
645 check(cu(connection, egl_frame_out, stream_inout))
646 }}
647}
648
649pub mod nvsci {
656 use super::*;
657 use crate::device::Device;
658
659 pub const SIGNAL: i32 = 0;
661 pub const WAIT: i32 = 1;
663
664 pub unsafe fn device_sync_attributes(
671 attr_list: *mut core::ffi::c_void,
672 device: &Device,
673 direction: i32,
674 ) -> Result<()> { unsafe {
675 let r = runtime()?;
676 let cu = r.cuda_device_get_nv_sci_sync_attributes()?;
677 check(cu(attr_list, device.ordinal(), direction))
678 }}
679}