1extern crate link_cplusplus;
41
42#[cfg(feature = "debug")]
43#[doc(hidden)]
44pub mod enum_debugs;
45mod prelude;
46pub mod vp;
47
48use ash::prelude::VkResult;
49use ash::vk;
50use prelude::*;
51use std::ffi::c_void;
52use vp::*;
53
54#[derive(Clone)]
56pub struct VulkanProfiles {
57 profiles_fn: vp::ProfilesFn,
58}
59
60impl VulkanProfiles {
61 pub fn linked() -> Self {
64 VulkanProfiles {
65 profiles_fn: vp::ProfilesFn::load_static(),
66 }
67 }
68
69 pub fn profiles_fn(&self) -> &vp::ProfilesFn {
71 &self.profiles_fn
72 }
73
74 pub unsafe fn get_profiles(&self) -> VkResult<Vec<ProfileProperties>> {
76 read_into_uninitialized_vector(|count, data| (self.profiles_fn.get_profiles)(count, data))
77 }
78
79 pub unsafe fn get_profile_fallbacks(
81 &self,
82 profile: &ProfileProperties,
83 ) -> VkResult<Vec<ProfileProperties>> {
84 read_into_uninitialized_vector(|count, data| {
85 (self.profiles_fn.get_profile_fallbacks)(profile, count, data)
86 })
87 }
88
89 pub unsafe fn get_instance_profile_support(
91 &self,
92 layer: Option<&::std::ffi::CStr>,
93 profile: &ProfileProperties,
94 ) -> VkResult<bool> {
95 let layer = match layer {
96 Some(layer) => layer.as_ptr(),
97 _ => std::ptr::null(),
98 };
99
100 let mut supported: vk::Bool32 = 0;
101 (self.profiles_fn.get_instance_profile_support)(layer, profile, &mut supported).result()?;
102 if supported == 0 {
103 Ok(false)
104 } else {
105 Ok(true)
106 }
107 }
108
109 pub unsafe fn create_instance(
111 &self,
112 entry: &ash::Entry,
113 create_info: &InstanceCreateInfo,
114 allocator: Option<vk::AllocationCallbacks>,
115 ) -> VkResult<ash::Instance> {
116 let allocator = match allocator {
117 Some(allocator) => &allocator,
118 _ => std::ptr::null(),
119 };
120
121 let mut instance = std::mem::zeroed();
122 (self.profiles_fn.create_instance)(create_info, allocator, &mut instance).result()?;
123 Ok(ash::Instance::load(entry.static_fn(), instance))
124 }
125
126 pub unsafe fn get_physical_device_profile_support(
128 &self,
129 instance: &ash::Instance,
130 physical_device: vk::PhysicalDevice,
131 profile: &ProfileProperties,
132 ) -> VkResult<bool> {
133 let mut supported: vk::Bool32 = 0;
134 (self.profiles_fn.get_physical_device_profile_support)(
135 instance.handle(),
136 physical_device,
137 profile,
138 &mut supported,
139 )
140 .result()?;
141 if supported == 0 {
142 Ok(false)
143 } else {
144 Ok(true)
145 }
146 }
147
148 pub unsafe fn create_device(
150 &self,
151 instance: &ash::Instance,
152 physical_device: vk::PhysicalDevice,
153 create_info: &DeviceCreateInfo,
154 allocator: Option<vk::AllocationCallbacks>,
155 ) -> VkResult<ash::Device> {
156 let allocator = match allocator {
157 Some(allocator) => &allocator,
158 _ => std::ptr::null(),
159 };
160
161 let mut device = std::mem::zeroed();
162 (self.profiles_fn.create_device)(physical_device, create_info, allocator, &mut device)
163 .result()?;
164 Ok(ash::Device::load(instance.fp_v1_0(), device))
165 }
166
167 pub unsafe fn get_profile_instance_extension_properties(
169 &self,
170 profile: &ProfileProperties,
171 ) -> VkResult<Vec<vk::ExtensionProperties>> {
172 read_into_uninitialized_vector(|count, data| {
173 (self.profiles_fn.get_profile_instance_extension_properties)(profile, count, data)
174 })
175 }
176
177 pub unsafe fn get_profile_device_extension_properties(
179 &self,
180 profile: &ProfileProperties,
181 ) -> VkResult<Vec<vk::ExtensionProperties>> {
182 read_into_uninitialized_vector(|count, data| {
183 (self.profiles_fn.get_profile_device_extension_properties)(profile, count, data)
184 })
185 }
186
187 pub unsafe fn get_profile_features(
191 &self,
192 profile: &ProfileProperties,
193 features: &mut vk::PhysicalDeviceFeatures2,
194 ) {
195 (self.profiles_fn.get_profile_features)(profile, features as *mut _ as *mut c_void);
196 }
197
198 pub unsafe fn get_profile_feature_structure_types(
200 &self,
201 profile: &ProfileProperties,
202 ) -> VkResult<Vec<vk::StructureType>> {
203 read_into_uninitialized_vector(|count, data| {
204 (self.profiles_fn.get_profile_feature_structure_types)(profile, count, data)
205 })
206 }
207
208 pub unsafe fn get_profile_properties(
212 &self,
213 profile: &ProfileProperties,
214 properties: &mut vk::PhysicalDeviceProperties2,
215 ) {
216 (self.profiles_fn.get_profile_properties)(profile, properties as *mut _ as *mut c_void);
217 }
218
219 pub unsafe fn get_profile_property_structure_types(
221 &self,
222 profile: &ProfileProperties,
223 ) -> VkResult<Vec<vk::StructureType>> {
224 read_into_uninitialized_vector(|count, data| {
225 (self.profiles_fn.get_profile_property_structure_types)(profile, count, data)
226 })
227 }
228
229 pub unsafe fn get_profile_queue_family_properties(
231 &self,
232 profile: &ProfileProperties,
233 properties: &mut [vk::QueueFamilyProperties2],
234 ) -> VkResult<()> {
235 let mut count = properties.len() as u32;
236 (self.profiles_fn.get_profile_queue_family_properties)(
237 profile,
238 &mut count,
239 properties.as_mut_ptr(),
240 )
241 .result()?;
242 assert_eq!(count as usize, properties.len());
243 Ok(())
244 }
245
246 pub unsafe fn get_profile_queue_family_structure_types(
248 &self,
249 profile: &ProfileProperties,
250 ) -> VkResult<Vec<vk::StructureType>> {
251 read_into_uninitialized_vector(|count, data| {
252 (self.profiles_fn.get_profile_queue_family_structure_types)(profile, count, data)
253 })
254 }
255
256 pub unsafe fn get_profile_formats(
258 &self,
259 profile: &ProfileProperties,
260 ) -> VkResult<Vec<vk::Format>> {
261 read_into_uninitialized_vector(|count, data| {
262 (self.profiles_fn.get_profile_formats)(profile, count, data)
263 })
264 }
265
266 pub unsafe fn get_profile_format_properties(
268 &self,
269 profile: &ProfileProperties,
270 format: vk::Format,
271 p_next: &mut vk::BaseOutStructure,
272 ) {
273 (self.profiles_fn.get_profile_format_properties)(
274 profile,
275 format,
276 p_next as *mut _ as *mut c_void,
277 );
278 }
279
280 pub unsafe fn get_profile_format_structure_types(
282 &self,
283 profile: &ProfileProperties,
284 ) -> VkResult<Vec<vk::StructureType>> {
285 read_into_uninitialized_vector(|count, data| {
286 (self.profiles_fn.get_profile_format_structure_types)(profile, count, data)
287 })
288 }
289}
290
291#[cfg(test)]
292mod tests {
293 use crate::vp;
294 use crate::VulkanProfiles;
295 use ash::vk;
296
297 fn create_instance(profiles: &VulkanProfiles) -> (vp::ProfileProperties, ash::Instance) {
298 let profile = vp::LunargDesktopPortability2021::profile_properties();
299 assert!(unsafe {
300 profiles
301 .get_instance_profile_support(None, &profile)
302 .unwrap()
303 });
304
305 let entry = ash::Entry::linked();
306
307 let instance_info = vk::InstanceCreateInfo::builder();
308 let vp_instance_info = vp::InstanceCreateInfo::builder()
309 .create_info(&instance_info)
310 .profile(&profile);
311
312 let instance = unsafe {
313 profiles
314 .create_instance(&entry, &vp_instance_info, None)
315 .unwrap()
316 };
317
318 (profile, instance)
319 }
320
321 #[test]
322 fn test_enumerate_profiles() {
323 let vk_profiles = VulkanProfiles::linked();
324
325 let profiles = unsafe { vk_profiles.get_profiles().unwrap() };
326
327 assert!(profiles.len() > 0);
328 for profile in &profiles {
329 println!(
330 "Profile {:?}: {:?}",
331 unsafe {
332 vk_profiles
333 .get_instance_profile_support(None, profile)
334 .unwrap()
335 },
336 profile
337 );
338 }
339
340 unsafe { vk_profiles.get_profile_fallbacks(&profiles[0]).unwrap() };
341 }
342
343 #[test]
344 fn test_enumerate_profile_details() {
345 let vk_profiles = VulkanProfiles::linked();
346
347 let profile = unsafe { vk_profiles.get_profiles().unwrap() }[0];
348
349 unsafe {
350 vk_profiles
351 .get_profile_instance_extension_properties(&profile)
352 .unwrap()
353 };
354 unsafe {
355 vk_profiles
356 .get_profile_device_extension_properties(&profile)
357 .unwrap()
358 };
359 unsafe {
360 vk_profiles
361 .get_profile_feature_structure_types(&profile)
362 .unwrap()
363 };
364 unsafe {
365 vk_profiles
366 .get_profile_property_structure_types(&profile)
367 .unwrap()
368 };
369 unsafe {
370 vk_profiles
371 .get_profile_queue_family_structure_types(&profile)
372 .unwrap()
373 };
374 unsafe { vk_profiles.get_profile_formats(&profile).unwrap() };
375 unsafe {
376 vk_profiles
377 .get_profile_property_structure_types(&profile)
378 .unwrap()
379 };
380 }
381
382 #[test]
383 fn test_create_instance() {
384 let (_, instance) = create_instance(&VulkanProfiles::linked());
385
386 unsafe { instance.destroy_instance(None) };
387 }
388
389 #[test]
390 fn test_create_device() {
391 let vk_profiles = VulkanProfiles::linked();
392
393 let (profile, instance) = create_instance(&vk_profiles);
394
395 let physical_device = unsafe { instance.enumerate_physical_devices().unwrap() }
396 .into_iter()
397 .find(|device| {
398 let props = unsafe { instance.get_physical_device_properties(*device) };
399 println!("PhysicalDevice: {:?}", unsafe {
400 std::ffi::CStr::from_ptr(props.device_name.as_ptr())
401 });
402 unsafe {
403 vk_profiles
404 .get_physical_device_profile_support(&instance, *device, &profile)
405 .expect("Error queueing physical device support")
406 }
407 })
408 .expect("Failed to find suitable physical device");
409
410 let queue_info = vk::DeviceQueueCreateInfo::builder()
411 .queue_family_index(0)
412 .queue_priorities(&[1.0]);
413
414 let device_info =
415 vk::DeviceCreateInfo::builder().queue_create_infos(std::slice::from_ref(&queue_info));
416
417 let vp_device_info = vp::DeviceCreateInfo::builder()
418 .create_info(&device_info)
419 .profile(&profile);
420
421 let device = unsafe {
422 vk_profiles
423 .create_device(&instance, physical_device, &vp_device_info, None)
424 .expect("Failed to create device")
425 };
426
427 unsafe { device.destroy_device(None) };
428
429 unsafe { instance.destroy_instance(None) };
430
431 println!("{:?}", vk::ImageUsageFlags::COLOR_ATTACHMENT);
432 }
433}