1use 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
12pub type Entry = RENDERDOC_API_1_4_1;
14
15#[repr(u32)]
17#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
18pub enum VersionCode {
19 V100 = 10000,
21 V101 = 10001,
23 V102 = 10002,
25 V110 = 10100,
27 V111 = 10101,
29 V112 = 10102,
31 V120 = 10200,
33 V130 = 10300,
35 V140 = 10400,
37 V141 = 10401,
39}
40
41pub trait Version {
43 const VERSION: VersionCode;
45
46 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 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
101pub trait HasPrevious: Version {
103 type Previous: Version;
105}
106
107#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
109pub enum V100 {}
110
111impl Version for V100 {
112 const VERSION: VersionCode = VersionCode::V100;
113}
114
115#[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#[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#[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#[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#[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#[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#[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}