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