renderdoc/
version.rs

1//! Entry points for the RenderDoc API.
2
3use std::ffi::c_void;
4use std::ptr;
5
6use libloading::{Library, Symbol};
7use once_cell::sync::OnceCell;
8use renderdoc_sys::RENDERDOC_API_1_4_1;
9
10use crate::error::Error;
11
12/// Entry point for the RenderDoc API.
13pub type Entry = RENDERDOC_API_1_4_1;
14
15/// Available versions of the RenderDoc API.
16#[repr(u32)]
17#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
18pub enum VersionCode {
19    /// Version 1.0.0.
20    V100 = 10000,
21    /// Version 1.0.1.
22    V101 = 10001,
23    /// Version 1.0.2.
24    V102 = 10002,
25    /// Version 1.1.0.
26    V110 = 10100,
27    /// Version 1.1.1.
28    V111 = 10101,
29    /// Version 1.1.2.
30    V112 = 10102,
31    /// Version 1.2.0.
32    V120 = 10200,
33    /// Version 1.3.0.
34    V130 = 10300,
35    /// Version 1.4.0.
36    V140 = 10400,
37    /// Version 1.4.1.
38    V141 = 10401,
39}
40
41/// Entry point into the RenderDoc API.
42pub trait Version {
43    /// Minimum compatible version number.
44    const VERSION: VersionCode;
45
46    /// Initializes a new instance of the RenderDoc API.
47    ///
48    /// # Safety
49    ///
50    /// This function is not thread-safe and should not be called on multiple threads at once.
51    fn load() -> Result<*mut Entry, Error> {
52        static LIBRARY: OnceCell<Library> = OnceCell::new();
53
54        type GetApiFn = unsafe extern "C" fn(ver: u32, out: *mut *mut c_void) -> i32;
55
56        #[cfg(windows)]
57        let lib_path = "renderdoc.dll";
58        #[cfg(all(unix, not(target_os = "android")))]
59        let lib_path = "librenderdoc.so";
60        #[cfg(target_os = "android")]
61        let lib_path = "libVkLayer_GLES_RenderDoc.so";
62
63        unsafe {
64            #[cfg(not(feature = "ci"))]
65            #[cfg(unix)]
66            let lib = LIBRARY
67                .get_or_try_init(|| {
68                    // TODO: Use constant from `libloading`, once added upstream.
69                    const RTLD_NOLOAD: i32 = 0x4;
70
71                    let flags = libloading::os::unix::RTLD_NOW | RTLD_NOLOAD;
72                    libloading::os::unix::Library::open(Some(lib_path), flags).map(Into::into)
73                })
74                .map_err(Error::library)?;
75
76            #[cfg(not(feature = "ci"))]
77            #[cfg(windows)]
78            let lib = LIBRARY
79                .get_or_try_init(|| {
80                    libloading::os::windows::Library::open_already_loaded(lib_path).map(Into::into)
81                })
82                .map_err(Error::library)?;
83
84            #[cfg(feature = "ci")]
85            let lib = LIBRARY
86                .get_or_try_init(|| Library::new(lib_path))
87                .map_err(Error::library)?;
88
89            let get_api: Symbol<GetApiFn> =
90                lib.get(b"RENDERDOC_GetAPI\0").map_err(Error::symbol)?;
91
92            let mut obj = ptr::null_mut();
93            match get_api(Self::VERSION as u32, &mut obj) {
94                1 => Ok(obj as *mut Entry),
95                _ => Err(Error::no_compatible_api()),
96            }
97        }
98    }
99}
100
101/// Trait for statically enforcing backwards compatibility.
102pub trait HasPrevious: Version {
103    /// API version which immediately precedes this one.
104    type Previous: Version;
105}
106
107/// Requests a minimum version number of 1.0.0.
108#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
109pub enum V100 {}
110
111impl Version for V100 {
112    const VERSION: VersionCode = VersionCode::V100;
113}
114
115/// Requests a minimum version number of 1.1.0.
116#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
117pub enum V110 {}
118
119impl Version for V110 {
120    const VERSION: VersionCode = VersionCode::V110;
121}
122
123impl HasPrevious for V110 {
124    type Previous = V100;
125}
126
127/// Requests a minimum version number of 1.1.1.
128#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
129pub enum V111 {}
130
131impl Version for V111 {
132    const VERSION: VersionCode = VersionCode::V111;
133}
134
135impl HasPrevious for V111 {
136    type Previous = V110;
137}
138
139/// Requests a minimum version number of 1.1.2.
140#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
141pub enum V112 {}
142
143impl Version for V112 {
144    const VERSION: VersionCode = VersionCode::V112;
145}
146
147impl HasPrevious for V112 {
148    type Previous = V111;
149}
150
151/// Requests a minimum version number of 1.2.0.
152#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
153pub enum V120 {}
154
155impl Version for V120 {
156    const VERSION: VersionCode = VersionCode::V120;
157}
158
159impl HasPrevious for V120 {
160    type Previous = V112;
161}
162
163/// Requests a minimum version number of 1.3.0.
164#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
165pub enum V130 {}
166
167impl Version for V130 {
168    const VERSION: VersionCode = VersionCode::V130;
169}
170
171impl HasPrevious for V130 {
172    type Previous = V120;
173}
174
175/// Requests a minimum version number of 1.4.0.
176#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
177pub enum V140 {}
178
179impl Version for V140 {
180    const VERSION: VersionCode = VersionCode::V140;
181}
182
183impl HasPrevious for V140 {
184    type Previous = V130;
185}
186
187/// Requests a minimum version number of 1.4.1.
188#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
189pub enum V141 {}
190
191impl Version for V141 {
192    const VERSION: VersionCode = VersionCode::V141;
193}
194
195impl HasPrevious for V141 {
196    type Previous = V140;
197}