gfx_renderdoc/
lib.rs

1#![warn(
2    trivial_casts,
3    trivial_numeric_casts,
4    unused_extern_crates,
5    unused_import_braces,
6    unused_qualifications
7)]
8
9//! RenderDoc integration - https://renderdoc.org/
10
11/// The dynamically loaded RenderDoc API function table
12#[repr(C)]
13#[derive(Debug)]
14pub struct RenderDocApi {
15    api: renderdoc_sys::RENDERDOC_API_1_4_1,
16    lib: libloading::Library,
17}
18
19unsafe impl Send for RenderDocApi {}
20
21unsafe impl Sync for RenderDocApi {}
22
23/// RenderDoc API type
24#[derive(Debug)]
25pub enum RenderDoc {
26    /// RenderDoc functionality is available
27    Available {
28        /// RenderDoc API with function pointers
29        api: RenderDocApi,
30    },
31    /// RenderDoc functionality is _not_ available
32    NotAvailable {
33        /// A description why renderdoc functionality is not available
34        reason: String,
35    },
36}
37
38impl RenderDoc {
39    pub unsafe fn new() -> Self {
40        type GetApiFn = unsafe extern "C" fn(version: u32, out: *mut *mut std::ffi::c_void) -> i32;
41
42        #[cfg(windows)]
43        let renderdoc_filename = "renderdoc.dll";
44        #[cfg(all(unix, not(target_os = "android")))]
45        let renderdoc_filename = "librenderdoc.so";
46        #[cfg(target_os = "android")]
47        let renderdoc_filename = "libVkLayer_GLES_RenderDoc.so";
48
49        let renderdoc_lib = match libloading::Library::new(renderdoc_filename) {
50            Ok(lib) => lib,
51            Err(e) => {
52                return RenderDoc::NotAvailable {
53                    reason: format!(
54                        "Unable to load renderdoc library '{}': {:?}",
55                        renderdoc_filename, e
56                    ),
57                }
58            }
59        };
60
61        let get_api: libloading::Symbol<GetApiFn> = match renderdoc_lib.get(b"RENDERDOC_GetAPI\0") {
62            Ok(api) => api,
63            Err(e) => {
64                return RenderDoc::NotAvailable {
65                    reason: format!(
66                        "Unable to get RENDERDOC_GetAPI from renderdoc library '{}': {:?}",
67                        renderdoc_filename, e
68                    ),
69                }
70            }
71        };
72        let mut obj = std::ptr::null_mut();
73        match get_api(10401, &mut obj) {
74            1 => RenderDoc::Available {
75                api: RenderDocApi {
76                    api: *(obj as *mut renderdoc_sys::RENDERDOC_API_1_4_1),
77                    lib: renderdoc_lib,
78                },
79            },
80            return_value => RenderDoc::NotAvailable {
81                reason: format!(
82                    "Unable to get API from renderdoc library '{}': {}",
83                    renderdoc_filename, return_value
84                ),
85            },
86        }
87    }
88}
89
90impl Default for RenderDoc {
91    fn default() -> Self {
92        if !cfg!(debug_assertions) {
93            return RenderDoc::NotAvailable {
94                reason: "RenderDoc support is only enabled with 'debug_assertions'".into(),
95            };
96        }
97        unsafe { Self::new() }
98    }
99}
100/// A implementation specific handle
101pub type Handle = *mut ::std::os::raw::c_void;
102
103impl RenderDoc {
104    /// Start a RenderDoc frame capture
105    pub unsafe fn start_frame_capture(&self, device_handle: Handle, window_handle: Handle) {
106        match self {
107            Self::Available { api: ref entry } => {
108                entry.api.StartFrameCapture.unwrap()(device_handle, window_handle);
109            }
110            Self::NotAvailable { ref reason } => {
111                log::warn!("Could not start RenderDoc frame capture: {}", reason)
112            }
113        };
114    }
115
116    /// End a RenderDoc frame capture
117    pub unsafe fn end_frame_capture(&self, device_handle: Handle, window_handle: Handle) {
118        match self {
119            Self::Available { api: ref entry } => {
120                entry.api.EndFrameCapture.unwrap()(device_handle, window_handle);
121            }
122            Self::NotAvailable { ref reason } => {
123                log::warn!("Could not end RenderDoc frame capture: {}", reason)
124            }
125        };
126    }
127}