1use erupt::{
3 cstr, vk, CustomEntryLoader, ExtendableFrom, InstanceLoader, InstanceLoaderBuilder,
4 LoaderError, SmallVec,
5};
6use std::{
7 ffi::{c_void, CStr, CString, NulError},
8 fmt,
9 os::raw::c_char,
10};
11use thiserror::Error;
12
13#[derive(Debug, Copy, Clone)]
15pub enum ValidationLayers {
16 Require,
18 Request,
20 Disable,
22}
23
24#[derive(Copy, Clone)]
26pub enum DebugMessenger {
27 Default,
30 Custom {
32 callback: vk::PFN_vkDebugUtilsMessengerCallbackEXT,
35 user_data_pointer: *mut c_void,
37 },
38 Disable,
40}
41
42pub unsafe extern "system" fn default_debug_callback(
44 message_severity: vk::DebugUtilsMessageSeverityFlagBitsEXT,
45 message_type: vk::DebugUtilsMessageTypeFlagsEXT,
46 p_callback_data: *const vk::DebugUtilsMessengerCallbackDataEXT,
47 _p_user_data: *mut c_void,
48) -> vk::Bool32 {
49 let message_severity = format!("{:?}", message_severity);
50 let message_severity = message_severity.strip_suffix("_EXT").unwrap();
51
52 let message_type = format!("{:?}", message_type);
53 let message_type = message_type.strip_suffix("_EXT").unwrap();
54
55 let message = CStr::from_ptr((*p_callback_data).p_message).to_string_lossy();
56 eprintln!("\x1b[1m{message_severity}\x1b[0m | \x1b[1m{message_type}\x1b[0m\n{message}");
58
59 vk::FALSE
60}
61
62#[derive(Clone)]
64pub struct InstanceMetadata {
65 instance_handle: vk::Instance,
66 api_version: u32,
67 enabled_layers: SmallVec<CString>,
68 enabled_extensions: SmallVec<CString>,
69}
70
71impl InstanceMetadata {
72 #[inline]
74 pub fn instance_handle(&self) -> vk::Instance {
75 self.instance_handle
76 }
77
78 #[inline]
80 pub fn api_version_raw(&self) -> u32 {
81 self.api_version
82 }
83
84 #[inline]
86 pub fn api_version_major(&self) -> u32 {
87 vk::api_version_major(self.api_version)
88 }
89
90 #[inline]
92 pub fn api_version_minor(&self) -> u32 {
93 vk::api_version_minor(self.api_version)
94 }
95
96 #[inline]
98 pub fn enabled_layers(&self) -> &[CString] {
99 &self.enabled_layers
100 }
101
102 #[inline]
104 pub unsafe fn is_layer_enabled(&self, layer: *const c_char) -> bool {
105 let qry = CStr::from_ptr(layer);
106 self.enabled_layers.iter().any(|e| e.as_c_str() == qry)
107 }
108
109 #[inline]
111 pub fn enabled_extensions(&self) -> &[CString] {
112 &self.enabled_extensions
113 }
114
115 #[inline]
117 pub unsafe fn is_extension_enabled(&self, extension: *const c_char) -> bool {
118 let qry = CStr::from_ptr(extension);
119 self.enabled_extensions.iter().any(|i| i.as_c_str() == qry)
120 }
121}
122
123impl fmt::Debug for InstanceMetadata {
124 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
125 fmt.debug_struct("InstanceMetadata")
126 .field(
127 "api_version",
128 &format_args!("{}.{}", self.api_version_major(), self.api_version_minor()),
129 )
130 .field("enabled_layers", &self.enabled_layers)
131 .field("enabled_extensions", &self.enabled_extensions)
132 .finish()
133 }
134}
135
136#[derive(Debug, Error)]
138pub enum InstanceCreationError {
139 #[error("vulkan error")]
141 VulkanError(#[from] vk::Result),
142 #[error("layers ({0:?}) not present")]
144 LayersNotPresent(SmallVec<CString>),
145 #[error("extensions ({0:?}) not present")]
147 ExtensionsNotPresent(SmallVec<CString>),
148 #[error("loader creation error")]
150 LoaderCreation(#[from] LoaderError),
151}
152
153pub struct InstanceBuilder<'a> {
155 loader_builder: InstanceLoaderBuilder<'a>,
156 app_name: Option<CString>,
157 app_version: Option<u32>,
158 engine_name: Option<CString>,
159 engine_version: Option<u32>,
160 required_api_version: u32,
161 requested_api_version: Option<u32>,
162 layers: SmallVec<(*const c_char, bool)>,
163 extensions: SmallVec<(*const c_char, bool)>,
164 debug_messenger: DebugMessenger,
165 debug_message_severity: vk::DebugUtilsMessageSeverityFlagsEXT,
166 debug_message_type: vk::DebugUtilsMessageTypeFlagsEXT,
167 enabled_validation_features: SmallVec<vk::ValidationFeatureEnableEXT>,
168 disabled_validation_features: SmallVec<vk::ValidationFeatureDisableEXT>,
169 allocator: Option<vk::AllocationCallbacks>,
170}
171
172impl<'a> InstanceBuilder<'a> {
173 #[inline]
175 pub fn new() -> Self {
176 InstanceBuilder::with_loader_builder(InstanceLoaderBuilder::new())
177 }
178
179 #[inline]
182 pub fn with_loader_builder(loader_builder: InstanceLoaderBuilder<'a>) -> Self {
183 InstanceBuilder {
184 loader_builder,
185 app_name: None,
186 app_version: None,
187 engine_name: None,
188 engine_version: None,
189 required_api_version: vk::API_VERSION_1_0,
190 requested_api_version: None,
191 layers: SmallVec::new(),
192 extensions: SmallVec::new(),
193 debug_messenger: DebugMessenger::Disable,
194 debug_message_severity: vk::DebugUtilsMessageSeverityFlagsEXT::WARNING_EXT
195 | vk::DebugUtilsMessageSeverityFlagsEXT::ERROR_EXT,
196 debug_message_type: vk::DebugUtilsMessageTypeFlagsEXT::GENERAL_EXT
197 | vk::DebugUtilsMessageTypeFlagsEXT::VALIDATION_EXT
198 | vk::DebugUtilsMessageTypeFlagsEXT::PERFORMANCE_EXT,
199 enabled_validation_features: SmallVec::new(),
200 disabled_validation_features: SmallVec::new(),
201 allocator: None,
202 }
203 }
204
205 #[inline]
207 pub fn app_name(mut self, app_name: &str) -> Result<Self, NulError> {
208 self.app_name = Some(CString::new(app_name)?);
209 Ok(self)
210 }
211
212 #[inline]
214 pub fn app_version(mut self, major: u32, minor: u32) -> Self {
215 self.app_version = Some(vk::make_api_version(0, major, minor, 0));
216 self
217 }
218
219 #[inline]
221 pub fn app_version_raw(mut self, app_version: u32) -> Self {
222 self.app_version = Some(app_version);
223 self
224 }
225
226 #[inline]
228 pub fn engine_name(mut self, engine_name: &str) -> Result<Self, NulError> {
229 self.engine_name = Some(CString::new(engine_name)?);
230 Ok(self)
231 }
232
233 #[inline]
235 pub fn engine_version(mut self, major: u32, minor: u32) -> Self {
236 self.engine_version = Some(vk::make_api_version(0, major, minor, 0));
237 self
238 }
239
240 #[inline]
242 pub fn engine_version_raw(mut self, engine_version: u32) -> Self {
243 self.engine_version = Some(engine_version);
244 self
245 }
246
247 #[inline]
249 pub fn require_api_version(mut self, major: u32, minor: u32) -> Self {
250 self.required_api_version = vk::make_api_version(0, major, minor, 0);
251 self
252 }
253
254 #[inline]
256 pub fn require_api_version_raw(mut self, api_version: u32) -> Self {
257 self.required_api_version = api_version;
258 self
259 }
260
261 #[inline]
264 pub fn request_api_version(mut self, major: u32, minor: u32) -> Self {
265 self.requested_api_version = Some(vk::make_api_version(0, major, minor, 0));
266 self
267 }
268
269 #[inline]
272 pub fn request_api_version_raw(mut self, api_version: u32) -> Self {
273 self.requested_api_version = Some(api_version);
274 self
275 }
276
277 #[inline]
279 pub fn request_layer(mut self, layer: *const c_char) -> Self {
280 self.layers.push((layer, false));
281 self
282 }
283
284 #[inline]
286 pub fn require_layer(mut self, layer: *const c_char) -> Self {
287 self.layers.push((layer, true));
288 self
289 }
290
291 #[inline]
293 pub fn request_extension(mut self, extension: *const c_char) -> Self {
294 self.extensions.push((extension, false));
295 self
296 }
297
298 #[inline]
300 pub fn require_extension(mut self, extension: *const c_char) -> Self {
301 self.extensions.push((extension, true));
302 self
303 }
304
305 #[cfg(feature = "surface")]
306 #[inline]
311 pub fn require_surface_extensions(
312 mut self,
313 window_handle: &impl raw_window_handle::HasRawWindowHandle,
314 ) -> Option<Self> {
315 let required_extensions =
316 erupt::utils::surface::enumerate_required_extensions(window_handle).ok()?;
317 self.extensions
318 .extend(required_extensions.into_iter().map(|name| (name, true)));
319 Some(self)
320 }
321
322 #[inline]
324 pub fn validation_layers(mut self, validation_layers: ValidationLayers) -> Self {
325 match validation_layers {
326 ValidationLayers::Require | ValidationLayers::Request => {
327 self.layers.push((
328 cstr!("VK_LAYER_KHRONOS_validation"),
329 matches!(validation_layers, ValidationLayers::Require),
330 ));
331
332 self.extensions
333 .push((vk::EXT_VALIDATION_FEATURES_EXTENSION_NAME, false));
334 }
335 ValidationLayers::Disable => (),
336 }
337
338 self
339 }
340
341 #[inline]
344 pub fn request_debug_messenger(mut self, debug_messenger: DebugMessenger) -> Self {
345 if !matches!(debug_messenger, DebugMessenger::Disable) {
346 self.extensions
347 .push((vk::EXT_DEBUG_UTILS_EXTENSION_NAME, false));
348 }
349
350 self.debug_messenger = debug_messenger;
351 self
352 }
353
354 #[inline]
356 pub fn debug_message_severity(
357 mut self,
358 severity: vk::DebugUtilsMessageSeverityFlagsEXT,
359 ) -> Self {
360 self.debug_message_severity = severity;
361 self
362 }
363
364 #[inline]
366 pub fn debug_message_type(mut self, ty: vk::DebugUtilsMessageTypeFlagsEXT) -> Self {
367 self.debug_message_type = ty;
368 self
369 }
370
371 #[inline]
373 pub fn enable_validation_feature(
374 mut self,
375 validation_feature: vk::ValidationFeatureEnableEXT,
376 ) -> Self {
377 self.enabled_validation_features.push(validation_feature);
378 self
379 }
380
381 #[inline]
383 pub fn disable_validation_feature(
384 mut self,
385 validation_feature: vk::ValidationFeatureDisableEXT,
386 ) -> Self {
387 self.disabled_validation_features.push(validation_feature);
388 self
389 }
390
391 #[inline]
393 pub fn allocation_callbacks(mut self, allocator: vk::AllocationCallbacks) -> Self {
394 self.allocator = Some(allocator);
395 self
396 }
397
398 pub unsafe fn build<T>(
402 self,
403 entry: &'a CustomEntryLoader<T>,
404 ) -> Result<
405 (
406 InstanceLoader,
407 Option<vk::DebugUtilsMessengerEXT>,
408 InstanceMetadata,
409 ),
410 InstanceCreationError,
411 > {
412 let mut required_api_version = self.required_api_version;
413 let instance_version = entry.instance_version();
414 if let Some(requested_api_version) = self.requested_api_version {
415 required_api_version =
416 required_api_version.max(requested_api_version.min(vk::make_api_version(
417 0,
418 vk::api_version_major(instance_version),
419 vk::api_version_minor(instance_version),
420 0,
421 )));
422 }
423
424 let mut app_info = vk::ApplicationInfoBuilder::new().api_version(required_api_version);
425
426 let app_name;
427 if let Some(val) = self.app_name {
428 app_name = val;
429 app_info = app_info.application_name(&app_name);
430 }
431
432 if let Some(app_version) = self.app_version {
433 app_info = app_info.application_version(app_version);
434 }
435
436 let engine_name;
437 if let Some(val) = self.engine_name {
438 engine_name = val;
439 app_info = app_info.engine_name(&engine_name);
440 }
441
442 if let Some(engine_version) = self.engine_version {
443 app_info = app_info.engine_version(engine_version);
444 }
445
446 let layer_properties = entry.enumerate_instance_layer_properties(None).result()?;
447 let mut enabled_layers = SmallVec::new();
448 let mut layers_not_present = SmallVec::new();
449 for (layer_name, required) in self.layers {
450 let cstr = CStr::from_ptr(layer_name);
451 let present = layer_properties
452 .iter()
453 .any(|supported_layer| CStr::from_ptr(supported_layer.layer_name.as_ptr()) == cstr);
454
455 match (required, present) {
456 (_, true) => enabled_layers.push(layer_name),
457 (true, false) => layers_not_present.push(cstr.to_owned()),
458 (false, false) => (),
459 }
460 }
461
462 if !layers_not_present.is_empty() {
463 return Err(InstanceCreationError::LayersNotPresent(layers_not_present));
464 }
465
466 let mut extension_properties = entry
467 .enumerate_instance_extension_properties(None, None)
468 .result()?;
469 for &layer_name in &enabled_layers {
470 extension_properties.extend({
471 let layer_name = CStr::from_ptr(layer_name);
472 entry
473 .enumerate_instance_extension_properties(Some(layer_name), None)
474 .result()?
475 .into_iter()
476 });
477 }
478
479 let mut enabled_extensions = SmallVec::new();
480 let mut extensions_not_present = SmallVec::new();
481 let debug_utils_cstr = CStr::from_ptr(vk::EXT_DEBUG_UTILS_EXTENSION_NAME);
482 let mut is_debug_utils_enabled = false;
483 let validation_features_cstr = CStr::from_ptr(vk::EXT_VALIDATION_FEATURES_EXTENSION_NAME);
484 let mut is_validation_features_enabled = false;
485 for (extension_name, required) in self.extensions {
486 let cstr = CStr::from_ptr(extension_name);
487 let present = extension_properties.iter().any(|supported_extension| {
488 CStr::from_ptr(supported_extension.extension_name.as_ptr()) == cstr
489 });
490
491 match (required, present) {
492 (_, true) => {
493 is_debug_utils_enabled |= cstr == debug_utils_cstr;
494 is_validation_features_enabled |= cstr == validation_features_cstr;
495 enabled_extensions.push(extension_name);
496 }
497 (true, false) => extensions_not_present.push(cstr.to_owned()),
498 (false, false) => (),
499 }
500 }
501
502 if !extensions_not_present.is_empty() {
503 return Err(InstanceCreationError::ExtensionsNotPresent(
504 extensions_not_present,
505 ));
506 }
507
508 let mut instance_info = vk::InstanceCreateInfoBuilder::new()
509 .application_info(&app_info)
510 .enabled_layer_names(&enabled_layers)
511 .enabled_extension_names(&enabled_extensions);
512
513 let should_create_debug_messenger = !matches!(
514 (&self.debug_messenger, is_debug_utils_enabled),
515 (DebugMessenger::Disable, _) | (_, false)
516 );
517
518 let messenger_info = should_create_debug_messenger.then(|| {
519 let messenger_info = vk::DebugUtilsMessengerCreateInfoEXTBuilder::new()
520 .message_severity(self.debug_message_severity)
521 .message_type(self.debug_message_type);
522 match self.debug_messenger {
523 DebugMessenger::Default => {
524 messenger_info.pfn_user_callback(Some(default_debug_callback))
525 }
526 DebugMessenger::Custom {
527 callback,
528 user_data_pointer,
529 } => messenger_info
530 .pfn_user_callback(Some(callback))
531 .user_data(user_data_pointer),
532 DebugMessenger::Disable => unreachable!(),
533 }
534 });
535
536 let mut instance_messenger_info;
537 if let Some(messenger_info) = messenger_info {
538 instance_messenger_info = *messenger_info;
539 instance_info = instance_info.extend_from(&mut instance_messenger_info);
540 }
541
542 let mut validation_features;
543 if is_validation_features_enabled {
544 validation_features = vk::ValidationFeaturesEXTBuilder::new()
545 .enabled_validation_features(&self.enabled_validation_features)
546 .disabled_validation_features(&self.disabled_validation_features);
547 instance_info = instance_info.extend_from(&mut validation_features);
548 }
549
550 let instance = self.loader_builder.build(entry, &instance_info)?;
551 let debug_utils_messenger = messenger_info
552 .map(|messenger_info| unsafe {
553 instance
554 .create_debug_utils_messenger_ext(&messenger_info, self.allocator.as_ref())
555 .result()
556 })
557 .transpose()?;
558 let instance_metadata = InstanceMetadata {
559 instance_handle: instance.handle,
560 api_version: app_info.api_version,
561 enabled_layers: enabled_layers
562 .into_iter()
563 .map(|ptr| unsafe { CStr::from_ptr(ptr).to_owned() })
564 .collect(),
565 enabled_extensions: enabled_extensions
566 .into_iter()
567 .map(|ptr| unsafe { CStr::from_ptr(ptr).to_owned() })
568 .collect(),
569 };
570
571 Ok((instance, debug_utils_messenger, instance_metadata))
572 }
573}
574
575impl<'a> Default for InstanceBuilder<'a> {
576 fn default() -> Self {
577 Self::new()
578 }
579}
580
581#[cfg(test)]
582mod tests {
583 use super::*;
584 use erupt::EntryLoader;
585
586 #[test]
587 fn basic() {
588 let entry = EntryLoader::new().unwrap();
589 let (instance, _debug_messenger, _metadata) =
590 unsafe { InstanceBuilder::new().build(&entry).unwrap() };
591
592 unsafe {
593 instance.destroy_instance(None);
594 }
595 }
596
597 #[test]
598 fn validation_and_messenger() {
599 let entry = EntryLoader::new().unwrap();
600 let (instance, debug_messenger, _metadata) = unsafe {
601 InstanceBuilder::new()
602 .validation_layers(ValidationLayers::Request)
603 .request_debug_messenger(DebugMessenger::Default)
604 .build(&entry)
605 .unwrap()
606 };
607
608 unsafe {
609 if let Some(debug_messenger) = debug_messenger {
610 instance.destroy_debug_utils_messenger_ext(debug_messenger, None);
611 }
612
613 instance.destroy_instance(None);
614 }
615 }
616}