1use std::convert::TryInto;
2use std::ffi::CStr;
3use std::fmt::Formatter;
4use std::os::raw::c_char;
5
6use erupt::{vk, ExtendableFromConst, ExtendableFromMut};
7#[cfg(feature = "tracing")]
8use tracing1::{error, info, warn};
9
10use crate::device::Queues;
11#[cfg(debug_assertions)]
12use crate::vk_debug::debug_utils_callback;
13use crate::{AscheError, Device, DeviceConfiguration, Lifetime, Result, Swapchain};
14
15#[derive(Clone, Debug)]
17pub struct InstanceConfiguration<'a> {
18 pub app_name: &'a str,
20 pub app_version: Version,
22 pub engine_name: &'a str,
24 pub engine_version: Version,
26 pub extensions: Vec<*const c_char>,
28}
29
30#[derive(Clone, Debug, Copy, Eq, PartialEq)]
32pub struct Version {
33 pub major: u32,
35 pub minor: u32,
37 pub patch: u32,
39}
40
41impl From<Version> for u32 {
42 fn from(v: Version) -> Self {
43 vk::make_api_version(0, v.major, v.minor, v.patch)
44 }
45}
46
47impl std::fmt::Display for Version {
48 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
49 write!(f, "{}.{}.{}", self.major, self.minor, self.patch)
50 }
51}
52
53#[derive(Debug)]
55pub struct Instance {
56 pub(crate) surface: vk::SurfaceKHR,
57 #[cfg(debug_assertions)]
58 debug_messenger: vk::DebugUtilsMessengerEXT,
59 raw: erupt::InstanceLoader,
60 _entry: erupt::EntryLoader,
61}
62
63impl Instance {
64 #[cfg_attr(feature = "profiling", profiling::function)]
66 pub fn new(
67 window_handle: &impl raw_window_handle::HasRawWindowHandle,
68 configuration: InstanceConfiguration,
69 ) -> Result<Instance> {
70 let entry = erupt::EntryLoader::new()?;
71
72 let app_name = std::ffi::CString::new(configuration.app_name.to_owned())?;
73 let engine_name = std::ffi::CString::new(configuration.engine_name.to_owned())?;
74
75 #[cfg(feature = "tracing")]
76 {
77 info!("Application name: {}", configuration.app_name);
78 info!("Application version: {}", configuration.app_version);
79 info!("Engine name: {}", configuration.engine_name);
80 info!("Engine version: {}", configuration.engine_version);
81 info!("Requesting Vulkan API version: 1.2.0");
82 }
83
84 let app_info = vk::ApplicationInfoBuilder::new()
85 .application_name(&app_name)
86 .application_version(configuration.app_version.into())
87 .engine_name(&engine_name)
88 .engine_version(configuration.engine_version.into())
89 .api_version(vk::make_api_version(0, 1, 2, 0));
90
91 let instance_extensions =
93 unsafe { entry.enumerate_instance_extension_properties(None, None) }.map_err(
94 |err| {
95 #[cfg(feature = "tracing")]
96 error!("Unable to enumerate instance extensions: {}", err);
97 AscheError::VkResult(err)
98 },
99 )?;
100
101 let instance_layers =
102 unsafe { entry.enumerate_instance_layer_properties(None) }.map_err(|err| {
103 #[cfg(feature = "tracing")]
104 error!("Unable to enumerate instance layers: {}", err);
105 AscheError::VkResult(err)
106 })?;
107
108 let extensions =
109 Self::create_instance_extensions(&configuration, &instance_extensions, window_handle)?;
110 let layers = Self::create_layers(&instance_layers);
111 let instance = Self::create_instance(&entry, &app_info, &extensions, &layers)?;
112 let surface =
113 unsafe { erupt::utils::surface::create_surface(&instance, window_handle, None) }
114 .map_err(|err| {
115 #[cfg(feature = "tracing")]
116 error!("Unable to create a surface: {}", err);
117 AscheError::VkResult(err)
118 })?;
119
120 #[cfg(debug_assertions)]
121 let debug_messenger = Self::create_debug_utils(&instance, instance_extensions)?;
122
123 Ok(Self {
124 _entry: entry,
125 raw: instance,
126 surface,
127 #[cfg(debug_assertions)]
128 debug_messenger,
129 })
130 }
131
132 #[inline]
134 pub(crate) fn raw(&self) -> &erupt::InstanceLoader {
135 &self.raw
136 }
137
138 #[cfg_attr(feature = "profiling", profiling::function)]
140 pub unsafe fn request_device<LT: Lifetime>(
141 self,
142 device_configuration: DeviceConfiguration,
143 ) -> Result<(Device<LT>, Swapchain, Queues)> {
144 Device::new(self, device_configuration)
145 }
146
147 #[cfg(debug_assertions)]
148 fn create_debug_utils(
149 instance: &erupt::InstanceLoader,
150 instance_extensions: Vec<vk::ExtensionProperties>,
151 ) -> Result<vk::DebugUtilsMessengerEXT> {
152 let debug_name = unsafe { CStr::from_ptr(vk::EXT_DEBUG_UTILS_EXTENSION_NAME) };
153 let debug_utils_found = instance_extensions
154 .iter()
155 .any(|props| unsafe { CStr::from_ptr(props.extension_name.as_ptr()) } == debug_name);
156
157 if debug_utils_found {
158 let info = vk::DebugUtilsMessengerCreateInfoEXTBuilder::new()
159 .message_severity(Self::vulkan_log_level())
160 .message_type(vk::DebugUtilsMessageTypeFlagsEXT::all())
161 .pfn_user_callback(Some(debug_utils_callback));
162
163 let utils = unsafe { instance.create_debug_utils_messenger_ext(&info, None) }.map_err(
164 |err| {
165 #[cfg(feature = "tracing")]
166 error!("Unable to create the debug utils messenger: {}", err);
167 AscheError::VkResult(err)
168 },
169 )?;
170 Ok(utils)
171 } else {
172 Err(AscheError::DebugUtilsMissing)
173 }
174 }
175
176 #[cfg(debug_assertions)]
177 fn vulkan_log_level() -> vk::DebugUtilsMessageSeverityFlagsEXT {
178 #[cfg(feature = "tracing")]
179 {
180 use tracing1::level_filters::LevelFilter;
181 match tracing1::level_filters::STATIC_MAX_LEVEL {
182 LevelFilter::OFF => vk::DebugUtilsMessageSeverityFlagsEXT::empty(),
183 LevelFilter::ERROR => vk::DebugUtilsMessageSeverityFlagsEXT::ERROR_EXT,
184 LevelFilter::WARN => {
185 vk::DebugUtilsMessageSeverityFlagsEXT::ERROR_EXT
186 | vk::DebugUtilsMessageSeverityFlagsEXT::WARNING_EXT
187 }
188 LevelFilter::INFO => {
189 vk::DebugUtilsMessageSeverityFlagsEXT::ERROR_EXT
190 | vk::DebugUtilsMessageSeverityFlagsEXT::WARNING_EXT
191 | vk::DebugUtilsMessageSeverityFlagsEXT::INFO_EXT
192 }
193 LevelFilter::DEBUG => {
194 vk::DebugUtilsMessageSeverityFlagsEXT::ERROR_EXT
195 | vk::DebugUtilsMessageSeverityFlagsEXT::WARNING_EXT
196 | vk::DebugUtilsMessageSeverityFlagsEXT::INFO_EXT
197 | vk::DebugUtilsMessageSeverityFlagsEXT::VERBOSE_EXT
198 }
199 LevelFilter::TRACE => vk::DebugUtilsMessageSeverityFlagsEXT::all(),
200 }
201 }
202 #[cfg(not(feature = "tracing"))]
203 {
204 vk::DebugUtilsMessageSeverityFlagsEXT::WARNING_EXT
205 }
206 }
207
208 fn create_instance(
209 entry: &erupt::EntryLoader,
210 app_info: &vk::ApplicationInfoBuilder,
211 instance_extensions: &[*const c_char],
212 layers: &[*const c_char],
213 ) -> Result<erupt::InstanceLoader> {
214 #[cfg(feature = "tracing")]
215 Self::print_extensions("instance", instance_extensions)?;
216
217 let create_info = vk::InstanceCreateInfoBuilder::new()
218 .flags(vk::InstanceCreateFlags::empty())
219 .application_info(app_info)
220 .enabled_layer_names(layers)
221 .enabled_extension_names(instance_extensions);
222
223 unsafe { erupt::InstanceLoader::new(entry, &create_info, None) }.map_err(|err| {
224 #[cfg(feature = "tracing")]
225 error!("Unable to create Vulkan instance: {}", err);
226 AscheError::LoaderError(err)
227 })
228 }
229
230 fn create_layers(instance_layers: &[vk::LayerProperties]) -> Vec<*const c_char> {
231 let mut layers = Vec::new();
232
233 layers.retain(|layer| {
234 let instance_layer = unsafe { CStr::from_ptr(*layer) };
235 let found = instance_layers.iter().any(|inst_layer| unsafe {
236 CStr::from_ptr(inst_layer.layer_name.as_ptr()) == instance_layer
237 });
238 if found {
239 true
240 } else {
241 #[cfg(feature = "tracing")]
242 warn!("Unable to find layer: {}", instance_layer.to_string_lossy());
243 false
244 }
245 });
246 layers
247 }
248
249 fn create_instance_extensions(
250 configuration: &InstanceConfiguration,
251 instance_extensions: &[vk::ExtensionProperties],
252 window_handle: &impl raw_window_handle::HasRawWindowHandle,
253 ) -> Result<Vec<*const c_char>> {
254 let mut extensions: Vec<*const c_char> = configuration.extensions.clone();
255
256 let required_extensions =
257 erupt::utils::surface::enumerate_required_extensions(window_handle).map_err(|err| {
258 #[cfg(feature = "tracing")]
259 error!(
260 "Unable to enumerate the required extensions for the surface creation: {}",
261 err
262 );
263 AscheError::VkResult(err)
264 })?;
265 extensions.extend(required_extensions.iter());
266
267 #[cfg(debug_assertions)]
268 extensions.push(vk::EXT_DEBUG_UTILS_EXTENSION_NAME);
269
270 Instance::retain_extensions(instance_extensions, &mut extensions);
272
273 Ok(extensions)
274 }
275
276 fn retain_extensions(
277 present_extensions: &[vk::ExtensionProperties],
278 requested_extensions: &mut Vec<*const i8>,
279 ) {
280 requested_extensions.retain(|ext| {
281 let extension = unsafe { CStr::from_ptr(*ext) };
282 present_extensions.iter().any(|inst_ext| unsafe {
283 CStr::from_ptr(inst_ext.extension_name.as_ptr()) == extension
284 })
285 });
286 }
287
288 pub(crate) fn find_physical_device(
289 &self,
290 device_type: vk::PhysicalDeviceType,
291 ) -> Result<(
292 vk::PhysicalDevice,
293 vk::PhysicalDeviceProperties,
294 vk::PhysicalDeviceDriverProperties,
295 )> {
296 let physical_devices =
297 unsafe { self.raw.enumerate_physical_devices(None) }.map_err(|err| {
298 #[cfg(feature = "tracing")]
299 error!("Unable to enumerate the physical devices: {}", err);
300 AscheError::VkResult(err)
301 })?;
302
303 let mut chosen = self.find_physical_device_inner_loop(device_type, &physical_devices);
305
306 if chosen.is_none() {
308 if device_type == vk::PhysicalDeviceType::DISCRETE_GPU {
309 chosen = self.find_physical_device_inner_loop(
310 vk::PhysicalDeviceType::INTEGRATED_GPU,
311 &physical_devices,
312 );
313 }
314 if device_type == vk::PhysicalDeviceType::INTEGRATED_GPU {
315 chosen = self.find_physical_device_inner_loop(
316 vk::PhysicalDeviceType::DISCRETE_GPU,
317 &physical_devices,
318 );
319 }
320 }
321
322 let chosen = chosen.ok_or(AscheError::RequestDeviceError)?;
323
324 Ok(chosen)
325 }
326
327 fn find_physical_device_inner_loop(
328 &self,
329 device_type: vk::PhysicalDeviceType,
330 physical_devices: &[vk::PhysicalDevice],
331 ) -> Option<(
332 vk::PhysicalDevice,
333 vk::PhysicalDeviceProperties,
334 vk::PhysicalDeviceDriverProperties,
335 )> {
336 let mut chosen = None;
337 for device in physical_devices {
338 let mut physical_device_driver_properties =
339 vk::PhysicalDeviceDriverProperties::default();
340 let physical_device_properties = vk::PhysicalDeviceProperties2Builder::new()
341 .extend_from(&mut physical_device_driver_properties);
342
343 let physical_device_properties = unsafe {
344 self.raw.get_physical_device_properties2(
345 *device,
346 Some(physical_device_properties.build()),
347 )
348 };
349
350 if physical_device_properties.properties.device_type == device_type {
351 chosen = Some((
352 *device,
353 physical_device_properties.properties,
354 physical_device_driver_properties,
355 ))
356 }
357 }
358 chosen
359 }
360
361 pub(crate) fn create_device(
370 &self,
371 physical_device: vk::PhysicalDevice,
372 configuration: DeviceConfiguration,
373 ) -> Result<(erupt::DeviceLoader, [u32; 3], [Vec<vk::Queue>; 3])> {
374 let queue_family_properties = unsafe {
375 self.raw
376 .get_physical_device_queue_family_properties(physical_device, None)
377 };
378
379 let graphics_queue_family_id = self.find_queue_family(
380 physical_device,
381 vk::QueueFlags::GRAPHICS,
382 &queue_family_properties,
383 )?;
384 let transfer_queue_family_id = self.find_queue_family(
385 physical_device,
386 vk::QueueFlags::TRANSFER,
387 &queue_family_properties,
388 )?;
389 let compute_queue_family_id = self.find_queue_family(
390 physical_device,
391 vk::QueueFlags::COMPUTE,
392 &queue_family_properties,
393 )?;
394
395 self.create_device_and_queues(
396 physical_device,
397 configuration,
398 graphics_queue_family_id,
399 transfer_queue_family_id,
400 compute_queue_family_id,
401 )
402 }
403
404 #[allow(clippy::as_conversions)]
405 fn create_device_and_queues(
406 &self,
407 physical_device: vk::PhysicalDevice,
408 configuration: DeviceConfiguration,
409 graphics_queue_family_id: u32,
410 transfer_queue_family_id: u32,
411 compute_queue_family_id: u32,
412 ) -> Result<(erupt::DeviceLoader, [u32; 3], [Vec<vk::Queue>; 3])> {
413 let queue_configuration = &configuration.queue_configuration;
414
415 let graphics_count = queue_configuration.graphics_queues.len();
416 let transfer_count = queue_configuration.transfer_queues.len();
417 let compute_count = queue_configuration.compute_queues.len();
418
419 if graphics_count + transfer_count + compute_count == 0 {
420 return Err(AscheError::NoQueueConfigured);
421 }
422
423 if graphics_count > 64 {
424 return Err(AscheError::QueueCountTooHigh(graphics_count));
425 }
426
427 if transfer_count > 64 {
428 return Err(AscheError::QueueCountTooHigh(transfer_count));
429 }
430
431 if compute_count > 64 {
432 return Err(AscheError::QueueCountTooHigh(compute_count));
433 }
434
435 if graphics_queue_family_id == transfer_queue_family_id
438 && transfer_queue_family_id != compute_queue_family_id
439 {
440 let mut p1 = Vec::with_capacity(graphics_count + transfer_count);
442 p1.extend_from_slice(&queue_configuration.graphics_queues);
443 p1.extend_from_slice(&queue_configuration.transfer_queues);
444
445 let mut p2 = Vec::with_capacity(compute_count);
446 p2.extend_from_slice(&queue_configuration.compute_queues);
447
448 let mut queue_infos = Vec::with_capacity(2);
449 if !p1.is_empty() {
450 queue_infos.push(
451 vk::DeviceQueueCreateInfoBuilder::new()
452 .queue_family_index(graphics_queue_family_id)
453 .queue_priorities(&p1),
454 );
455 }
456
457 if !p2.is_empty() {
458 queue_infos.push(
459 vk::DeviceQueueCreateInfoBuilder::new()
460 .queue_family_index(compute_queue_family_id)
461 .queue_priorities(&p2),
462 );
463 }
464
465 let device =
466 self.create_logical_device(physical_device, configuration, &queue_infos)?;
467
468 let g_q = (0..graphics_count)
469 .map(|i| unsafe { device.get_device_queue(graphics_queue_family_id, i as u32) })
470 .collect::<_>();
471
472 let t_q = (graphics_count..graphics_count + transfer_count)
473 .map(|i| unsafe { device.get_device_queue(graphics_queue_family_id, i as u32) })
474 .collect::<_>();
475
476 let c_q = (0..compute_count)
477 .map(|i| unsafe { device.get_device_queue(compute_queue_family_id, i as u32) })
478 .collect::<_>();
479
480 Ok((
481 device,
482 [
483 compute_queue_family_id,
484 graphics_queue_family_id,
485 transfer_queue_family_id,
486 ],
487 [c_q, g_q, t_q],
488 ))
489 } else if graphics_queue_family_id != transfer_queue_family_id
490 && transfer_queue_family_id == compute_queue_family_id
491 {
492 let mut p1 = Vec::with_capacity(graphics_count);
494 p1.extend_from_slice(&queue_configuration.graphics_queues);
495
496 let mut p2 = Vec::with_capacity(transfer_count + compute_count);
497 p2.extend_from_slice(&queue_configuration.transfer_queues);
498 p2.extend_from_slice(&queue_configuration.compute_queues);
499
500 let mut queue_infos = Vec::with_capacity(2);
501 if !p1.is_empty() {
502 queue_infos.push(
503 vk::DeviceQueueCreateInfoBuilder::new()
504 .queue_family_index(graphics_queue_family_id)
505 .queue_priorities(&p1),
506 );
507 }
508 if !p2.is_empty() {
509 queue_infos.push(
510 vk::DeviceQueueCreateInfoBuilder::new()
511 .queue_family_index(transfer_queue_family_id)
512 .queue_priorities(&p2),
513 );
514 }
515
516 let device =
517 self.create_logical_device(physical_device, configuration, &queue_infos)?;
518 let g_q = (0..graphics_count)
519 .map(|i| unsafe { device.get_device_queue(graphics_queue_family_id, i as u32) })
520 .collect::<_>();
521
522 let t_q = (0..transfer_count)
523 .map(|i| unsafe { device.get_device_queue(transfer_queue_family_id, i as u32) })
524 .collect::<_>();
525
526 let c_q = (transfer_count..transfer_count + compute_count)
527 .map(|i| unsafe { device.get_device_queue(transfer_queue_family_id, i as u32) })
528 .collect::<_>();
529
530 Ok((
531 device,
532 [
533 compute_queue_family_id,
534 graphics_queue_family_id,
535 transfer_queue_family_id,
536 ],
537 [c_q, g_q, t_q],
538 ))
539 } else if graphics_queue_family_id == compute_queue_family_id
540 && graphics_queue_family_id != transfer_queue_family_id
541 {
542 let mut p1 = Vec::with_capacity(graphics_count + compute_count);
544 p1.extend_from_slice(&queue_configuration.graphics_queues);
545 p1.extend_from_slice(&queue_configuration.compute_queues);
546
547 let mut p2 = Vec::with_capacity(transfer_count);
548 p2.extend_from_slice(&queue_configuration.transfer_queues);
549
550 let mut queue_infos = Vec::with_capacity(2);
551 if !p1.is_empty() {
552 queue_infos.push(
553 vk::DeviceQueueCreateInfoBuilder::new()
554 .queue_family_index(graphics_queue_family_id)
555 .queue_priorities(&p1),
556 );
557 }
558 if !p2.is_empty() {
559 queue_infos.push(
560 vk::DeviceQueueCreateInfoBuilder::new()
561 .queue_family_index(transfer_queue_family_id)
562 .queue_priorities(&p2),
563 );
564 }
565
566 let device =
567 self.create_logical_device(physical_device, configuration, &queue_infos)?;
568
569 let g_q = (0..graphics_count)
570 .map(|i| unsafe { device.get_device_queue(graphics_queue_family_id, i as u32) })
571 .collect::<_>();
572
573 let c_q = (graphics_count..graphics_count + compute_count)
574 .map(|i| unsafe { device.get_device_queue(graphics_queue_family_id, i as u32) })
575 .collect::<_>();
576
577 let t_q = (0..transfer_count)
578 .map(|i| unsafe { device.get_device_queue(transfer_queue_family_id, i as u32) })
579 .collect::<_>();
580
581 Ok((
582 device,
583 [
584 compute_queue_family_id,
585 graphics_queue_family_id,
586 transfer_queue_family_id,
587 ],
588 [c_q, g_q, t_q],
589 ))
590 } else if graphics_queue_family_id == transfer_queue_family_id
591 && transfer_queue_family_id == compute_queue_family_id
592 {
593 let mut p1 = Vec::with_capacity(graphics_count + transfer_count + compute_count);
595 p1.extend_from_slice(&queue_configuration.graphics_queues);
596 p1.extend_from_slice(&queue_configuration.transfer_queues);
597 p1.extend_from_slice(&queue_configuration.compute_queues);
598
599 let queue_infos = [vk::DeviceQueueCreateInfoBuilder::new()
600 .queue_family_index(graphics_queue_family_id)
601 .queue_priorities(&p1)];
602 let device =
603 self.create_logical_device(physical_device, configuration, &queue_infos)?;
604 let g_q = (0..graphics_count)
605 .map(|i| unsafe { device.get_device_queue(graphics_queue_family_id, i as u32) })
606 .collect::<_>();
607
608 let t_q = (graphics_count..graphics_count + transfer_count)
609 .map(|i| unsafe { device.get_device_queue(graphics_queue_family_id, i as u32) })
610 .collect::<_>();
611
612 let c_q = (graphics_count + transfer_count
613 ..graphics_count + transfer_count + compute_count)
614 .map(|i| unsafe { device.get_device_queue(graphics_queue_family_id, i as u32) })
615 .collect::<_>();
616
617 Ok((
618 device,
619 [
620 compute_queue_family_id,
621 graphics_queue_family_id,
622 transfer_queue_family_id,
623 ],
624 [c_q, g_q, t_q],
625 ))
626 } else {
627 let mut p1 = Vec::with_capacity(graphics_count);
629 p1.extend_from_slice(&queue_configuration.graphics_queues);
630
631 let mut p2 = Vec::with_capacity(transfer_count);
632 p2.extend_from_slice(&queue_configuration.transfer_queues);
633
634 let mut p3 = Vec::with_capacity(compute_count);
635 p3.extend_from_slice(&queue_configuration.compute_queues);
636
637 let mut queue_infos = Vec::with_capacity(2);
638 if !p1.is_empty() {
639 queue_infos.push(
640 vk::DeviceQueueCreateInfoBuilder::new()
641 .queue_family_index(graphics_queue_family_id)
642 .queue_priorities(&p1),
643 );
644 }
645 if !p2.is_empty() {
646 queue_infos.push(
647 vk::DeviceQueueCreateInfoBuilder::new()
648 .queue_family_index(transfer_queue_family_id)
649 .queue_priorities(&p2),
650 );
651 }
652 if !p3.is_empty() {
653 queue_infos.push(
654 vk::DeviceQueueCreateInfoBuilder::new()
655 .queue_family_index(compute_queue_family_id)
656 .queue_priorities(&p3),
657 );
658 }
659
660 let device =
661 self.create_logical_device(physical_device, configuration, &queue_infos)?;
662
663 let g_q = (0..graphics_count)
664 .map(|i| unsafe { device.get_device_queue(graphics_queue_family_id, i as u32) })
665 .collect::<_>();
666
667 let t_q = (0..transfer_count)
668 .map(|i| unsafe { device.get_device_queue(transfer_queue_family_id, i as u32) })
669 .collect::<_>();
670
671 let c_q = (0..compute_count)
672 .map(|i| unsafe { device.get_device_queue(compute_queue_family_id, i as u32) })
673 .collect::<_>();
674
675 Ok((
676 device,
677 [
678 compute_queue_family_id,
679 graphics_queue_family_id,
680 transfer_queue_family_id,
681 ],
682 [c_q, g_q, t_q],
683 ))
684 }
685 }
686
687 fn create_logical_device(
688 &self,
689 physical_device: vk::PhysicalDevice,
690 mut configuration: DeviceConfiguration,
691 queue_infos: &[vk::DeviceQueueCreateInfoBuilder],
692 ) -> Result<erupt::DeviceLoader> {
693 let device_extensions = self.create_device_extensions(physical_device, &configuration)?;
694
695 #[cfg(feature = "tracing")]
696 Self::print_extensions("device", &device_extensions)?;
697
698 let robustness2_name = unsafe { CStr::from_ptr(vk::EXT_ROBUSTNESS_2_EXTENSION_NAME) };
699 let robustness2_enabled = device_extensions
700 .iter()
701 .any(|ext| unsafe { CStr::from_ptr(*ext) == robustness2_name });
702
703 let raytracing_name =
704 unsafe { CStr::from_ptr(vk::KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME) };
705 let raytracing_enabled = device_extensions
706 .iter()
707 .any(|ext| unsafe { CStr::from_ptr(*ext) == raytracing_name });
708
709 let acceleration_name =
710 unsafe { CStr::from_ptr(vk::KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME) };
711 let acceleration_structure_enabled = device_extensions
712 .iter()
713 .any(|ext| unsafe { CStr::from_ptr(*ext) == acceleration_name });
714
715 let (
716 physical_features,
717 physical_features11,
718 physical_features12,
719 physical_features_synchronization2,
720 physical_device_robustness2_features,
721 physical_features_raytracing,
722 physical_features_acceleration_structure,
723 ) = self.collect_physical_device_features(
724 physical_device,
725 robustness2_enabled,
726 raytracing_enabled,
727 acceleration_structure_enabled,
728 );
729
730 let features = if let Some(features) = configuration.features_v1_0.take() {
731 features
732 } else {
733 vk::PhysicalDeviceFeaturesBuilder::new()
734 };
735 let features11 = if let Some(features) = configuration.features_v1_1.take() {
736 features
737 } else {
738 vk::PhysicalDeviceVulkan11FeaturesBuilder::new()
739 };
740 let mut features12 = if let Some(features) = configuration.features_v1_2.take() {
741 features
742 } else {
743 vk::PhysicalDeviceVulkan12FeaturesBuilder::new()
744 };
745 let device_robustness2_features =
746 if let Some(features) = configuration.features_robustness2.take() {
747 features
748 } else {
749 vk::PhysicalDeviceRobustness2FeaturesEXTBuilder::new()
750 };
751 let features_raytracing = if let Some(features) = configuration.features_raytracing.take() {
752 features
753 } else {
754 vk::PhysicalDeviceRayTracingPipelineFeaturesKHRBuilder::new()
755 };
756 let features_acceleration_structure =
757 if let Some(features) = configuration.features_acceleration_structure.take() {
758 features
759 } else {
760 vk::PhysicalDeviceAccelerationStructureFeaturesKHRBuilder::new()
761 };
762
763 features12 = features12.timeline_semaphore(true);
764
765 #[cfg(feature = "vk-buffer-device-address")]
766 {
767 features12 = features12.buffer_device_address(true);
768 }
769
770 let features_synchronization2 =
771 vk::PhysicalDeviceSynchronization2FeaturesKHRBuilder::new().synchronization2(true);
772
773 check_features(
774 &physical_features,
775 &physical_features11,
776 &physical_features12,
777 &physical_features_synchronization2,
778 &physical_device_robustness2_features,
779 &physical_features_raytracing,
780 &physical_features_acceleration_structure,
781 &features,
782 &features11,
783 &features12,
784 &features_synchronization2,
785 &device_robustness2_features,
786 &features_raytracing,
787 &features_acceleration_structure,
788 )?;
789
790 let device_create_info = vk::DeviceCreateInfoBuilder::new()
791 .queue_create_infos(queue_infos)
792 .enabled_extension_names(&device_extensions)
793 .enabled_features(&features)
794 .extend_from(&features11)
795 .extend_from(&features12)
796 .extend_from(&features_synchronization2);
797
798 let device_create_info = if robustness2_enabled {
799 device_create_info.extend_from(&device_robustness2_features)
800 } else {
801 device_create_info
802 };
803
804 let device_create_info = if raytracing_enabled {
805 device_create_info.extend_from(&features_raytracing)
806 } else {
807 device_create_info
808 };
809
810 let device_create_info = if acceleration_structure_enabled {
811 device_create_info.extend_from(&features_acceleration_structure)
812 } else {
813 device_create_info
814 };
815
816 let device = unsafe {
817 erupt::DeviceLoader::new(&self.raw, physical_device, &device_create_info, None)
818 }?;
819
820 Ok(device)
821 }
822
823 #[cfg(feature = "tracing")]
824 fn print_extensions(what: &str, extensions: &[*const i8]) -> Result<()> {
825 info!("Loading {} extensions:", what);
826 for extension in extensions.iter() {
827 let ext = unsafe { CStr::from_ptr(*extension).to_str() }?;
828 info!("- {}", ext);
829 }
830 Ok(())
831 }
832
833 fn collect_physical_device_features(
834 &self,
835 physical_device: vk::PhysicalDevice,
836 robustness2_enabled: bool,
837 raytracing_enabled: bool,
838 acceleration_structure_enabled: bool,
839 ) -> (
840 vk::PhysicalDeviceFeatures,
841 vk::PhysicalDeviceVulkan11FeaturesBuilder,
842 vk::PhysicalDeviceVulkan12FeaturesBuilder,
843 vk::PhysicalDeviceSynchronization2FeaturesKHRBuilder,
844 vk::PhysicalDeviceRobustness2FeaturesEXTBuilder,
845 vk::PhysicalDeviceRayTracingPipelineFeaturesKHRBuilder,
846 vk::PhysicalDeviceAccelerationStructureFeaturesKHRBuilder,
847 ) {
848 let mut physical_features11 = vk::PhysicalDeviceVulkan11FeaturesBuilder::new();
849 let mut physical_features12 = vk::PhysicalDeviceVulkan12FeaturesBuilder::new();
850
851 let mut physical_feature_synchronization2 =
852 vk::PhysicalDeviceSynchronization2FeaturesKHRBuilder::new();
853
854 let mut physical_device_robustness2_features =
855 vk::PhysicalDeviceRobustness2FeaturesEXTBuilder::new();
856
857 let mut physical_features_raytracing =
858 vk::PhysicalDeviceRayTracingPipelineFeaturesKHRBuilder::new();
859 let mut physical_features_acceleration =
860 vk::PhysicalDeviceAccelerationStructureFeaturesKHRBuilder::new();
861
862 let physical_features = unsafe {
863 let physical_features = vk::PhysicalDeviceFeatures2Builder::new()
864 .extend_from(&mut physical_features11)
865 .extend_from(&mut physical_features12)
866 .extend_from(&mut physical_feature_synchronization2);
867
868 let physical_features = if robustness2_enabled {
869 physical_features.extend_from(&mut physical_device_robustness2_features)
870 } else {
871 physical_features
872 };
873
874 let physical_features = if raytracing_enabled {
875 physical_features.extend_from(&mut physical_features_raytracing)
876 } else {
877 physical_features
878 };
879
880 let physical_features = if acceleration_structure_enabled {
881 physical_features.extend_from(&mut physical_features_acceleration)
882 } else {
883 physical_features
884 };
885
886 self.raw
887 .get_physical_device_features2(physical_device, Some(physical_features.build()))
888 };
889
890 (
891 physical_features.features,
892 physical_features11,
893 physical_features12,
894 physical_feature_synchronization2,
895 physical_device_robustness2_features,
896 physical_features_raytracing,
897 physical_features_acceleration,
898 )
899 }
900
901 fn create_device_extensions(
902 &self,
903 physical_device: vk::PhysicalDevice,
904 configuration: &DeviceConfiguration,
905 ) -> Result<Vec<*const c_char>> {
906 let mut extensions: Vec<*const c_char> = configuration.extensions.clone();
907
908 extensions.push(vk::KHR_SWAPCHAIN_EXTENSION_NAME);
909 extensions.push(vk::KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
910
911 let device_extensions = unsafe {
913 self.raw
914 .enumerate_device_extension_properties(physical_device, None, None)
915 }
916 .map_err(|err| {
917 #[cfg(feature = "tracing")]
918 error!(
919 "Unable to enumerate the device extension properties: {}",
920 err
921 );
922 AscheError::VkResult(err)
923 })?;
924
925 Instance::retain_extensions(&device_extensions, &mut extensions);
927
928 Ok(extensions)
929 }
930
931 fn find_queue_family(
932 &self,
933 physical_device: vk::PhysicalDevice,
934 target_family: vk::QueueFlags,
935 queue_family_properties: &[vk::QueueFamilyProperties],
936 ) -> Result<u32> {
937 let mut queue_id = None;
938 for (id, family) in queue_family_properties.iter().enumerate() {
939 let surface_supported = unsafe {
940 self.raw.get_physical_device_surface_support_khr(
941 physical_device,
942 id.try_into()?,
943 self.surface,
944 )
945 }
946 .map_err(|err| {
947 #[cfg(feature = "tracing")]
948 error!("Unable to get the physical device surface support: {}", err);
949 AscheError::VkResult(err)
950 })?;
951
952 match target_family {
953 vk::QueueFlags::GRAPHICS => {
954 if family.queue_count > 0
955 && family.queue_flags.contains(vk::QueueFlags::GRAPHICS)
956 && surface_supported
957 {
958 queue_id = Some(id.try_into()?);
959 }
960 }
961 vk::QueueFlags::TRANSFER => {
962 if family.queue_count > 0
963 && family.queue_flags.contains(vk::QueueFlags::TRANSFER)
964 && (queue_id.is_none()
965 || !family.queue_flags.contains(vk::QueueFlags::GRAPHICS)
966 && !family.queue_flags.contains(vk::QueueFlags::COMPUTE))
967 {
968 queue_id = Some(id.try_into()?);
969 }
970 }
971 vk::QueueFlags::COMPUTE => {
972 if family.queue_count > 0
973 && family.queue_flags.contains(vk::QueueFlags::COMPUTE)
974 && (queue_id.is_none()
975 || !family.queue_flags.contains(vk::QueueFlags::GRAPHICS))
976 {
977 queue_id = Some(id.try_into()?);
978 }
979 }
980 _ => return Err(AscheError::QueueFamilyNotFound("unknown".to_string())),
981 }
982 }
983
984 if let Some(id) = queue_id {
985 #[cfg(feature = "tracing")]
986 info!("Selected {:?} queue has family index {}", target_family, id);
987
988 Ok(id)
989 } else {
990 match target_family {
991 vk::QueueFlags::COMPUTE => {
992 Err(AscheError::QueueFamilyNotFound("compute".to_string()))
993 }
994 vk::QueueFlags::GRAPHICS => {
995 Err(AscheError::QueueFamilyNotFound("graphic".to_string()))
996 }
997 vk::QueueFlags::TRANSFER => {
998 Err(AscheError::QueueFamilyNotFound("transfer".to_string()))
999 }
1000 _ => Err(AscheError::QueueFamilyNotFound("unknown".to_string())),
1001 }
1002 }
1003 }
1004}
1005
1006macro_rules! impl_feature_assemble {
1007 (
1008 $present:ident, $wanted:ident, $present_vector:ident, $wanted_vector:ident;
1009 {
1010 $($name:ident)*
1011 }
1012 ) => {
1013 $(if $present.$name != 0 {
1014 $present_vector.push(stringify!($name))
1015 })*
1016 $(if $wanted.$name != 0 {
1017 $wanted_vector.push(stringify!($name))
1018 })*
1019 };
1020}
1021
1022#[allow(unused_mut)]
1023#[allow(clippy::too_many_arguments)]
1024fn check_features(
1025 physical_features: &vk::PhysicalDeviceFeatures,
1026 physical_features11: &vk::PhysicalDeviceVulkan11FeaturesBuilder,
1027 physical_features12: &vk::PhysicalDeviceVulkan12FeaturesBuilder,
1028 physical_features_synchronization2: &vk::PhysicalDeviceSynchronization2FeaturesKHRBuilder,
1029 physical_device_robustness2_features: &vk::PhysicalDeviceRobustness2FeaturesEXTBuilder,
1030 physical_features_raytracing: &vk::PhysicalDeviceRayTracingPipelineFeaturesKHRBuilder,
1031 physical_features_acceleration_structure: &vk::PhysicalDeviceAccelerationStructureFeaturesKHRBuilder,
1032 features: &vk::PhysicalDeviceFeaturesBuilder,
1033 features11: &vk::PhysicalDeviceVulkan11FeaturesBuilder,
1034 features12: &vk::PhysicalDeviceVulkan12FeaturesBuilder,
1035 features_synchronization2: &vk::PhysicalDeviceSynchronization2FeaturesKHRBuilder,
1036 device_robustness2_features: &vk::PhysicalDeviceRobustness2FeaturesEXTBuilder,
1037 features_raytracing: &vk::PhysicalDeviceRayTracingPipelineFeaturesKHRBuilder,
1038 features_acceleration_structure: &vk::PhysicalDeviceAccelerationStructureFeaturesKHRBuilder,
1039) -> Result<()> {
1040 let mut physical_features_list: Vec<&str> = Vec::with_capacity(54);
1041 let mut physical_features11_list: Vec<&str> = Vec::with_capacity(11);
1042 let mut physical_features12_list: Vec<&str> = Vec::with_capacity(46);
1043 let mut physical_features_synchronization2_list: Vec<&str> = Vec::with_capacity(1);
1044 let mut physical_device_robustness2_features_list: Vec<&str> = Vec::with_capacity(3);
1045 let mut physical_features_raytracing_list: Vec<&str> = Vec::with_capacity(5);
1046 let mut physical_features_acceleration_structure_list: Vec<&str> = Vec::with_capacity(5);
1047
1048 let mut features_list: Vec<&str> = Vec::with_capacity(54);
1049 let mut features11_list: Vec<&str> = Vec::with_capacity(11);
1050 let mut features12_list: Vec<&str> = Vec::with_capacity(46);
1051 let mut features_synchronization2_list: Vec<&str> = Vec::with_capacity(1);
1052 let mut device_robustness2_features_list: Vec<&str> = Vec::with_capacity(3);
1053 let mut features_raytracing_list: Vec<&str> = Vec::with_capacity(5);
1054 let mut features_acceleration_structure_list: Vec<&str> = Vec::with_capacity(5);
1055
1056 impl_feature_assemble!(
1057 physical_features, features, physical_features_list, features_list;
1058 {
1059 robust_buffer_access
1060 full_draw_index_uint32
1061 image_cube_array
1062 independent_blend
1063 geometry_shader
1064 tessellation_shader
1065 sample_rate_shading
1066 dual_src_blend
1067 logic_op
1068 multi_draw_indirect
1069 draw_indirect_first_instance
1070 depth_clamp
1071 depth_bias_clamp
1072 fill_mode_non_solid
1073 depth_bounds
1074 wide_lines
1075 large_points
1076 alpha_to_one
1077 multi_viewport
1078 sampler_anisotropy
1079 texture_compression_etc2
1080 texture_compression_astc_ldr
1081 texture_compression_bc
1082 occlusion_query_precise
1083 pipeline_statistics_query
1084 vertex_pipeline_stores_and_atomics
1085 fragment_stores_and_atomics
1086 shader_tessellation_and_geometry_point_size
1087 shader_image_gather_extended
1088 shader_storage_image_extended_formats
1089 shader_storage_image_multisample
1090 shader_storage_image_read_without_format
1091 shader_storage_image_write_without_format
1092 shader_uniform_buffer_array_dynamic_indexing
1093 shader_sampled_image_array_dynamic_indexing
1094 shader_storage_buffer_array_dynamic_indexing
1095 shader_storage_image_array_dynamic_indexing
1096 shader_clip_distance
1097 shader_cull_distance
1098 shader_float64
1099 shader_int64
1100 shader_int16
1101 shader_resource_residency
1102 shader_resource_min_lod
1103 sparse_binding
1104 sparse_residency_buffer
1105 sparse_residency_image2_d
1106 sparse_residency_image3_d
1107 sparse_residency2_samples
1108 sparse_residency4_samples
1109 sparse_residency8_samples
1110 sparse_residency16_samples
1111 sparse_residency_aliased
1112 variable_multisample_rate
1113 inherited_queries
1114 }
1115 );
1116
1117 impl_feature_assemble!(
1118 physical_features11, features11, physical_features11_list, features11_list;
1119 {
1120 storage_buffer16_bit_access
1121 uniform_and_storage_buffer16_bit_access
1122 storage_push_constant16
1123 storage_input_output16
1124 multiview
1125 multiview_geometry_shader
1126 multiview_tessellation_shader
1127 variable_pointers_storage_buffer
1128 variable_pointers
1129 protected_memory
1130 sampler_ycbcr_conversion
1131 shader_draw_parameters
1132 }
1133 );
1134
1135 impl_feature_assemble!(
1136 physical_features12, features12, physical_features12_list, features12_list;
1137 {
1138 sampler_mirror_clamp_to_edge
1139 draw_indirect_count
1140 storage_buffer8_bit_access
1141 uniform_and_storage_buffer8_bit_access
1142 storage_push_constant8
1143 shader_buffer_int64_atomics
1144 shader_shared_int64_atomics
1145 shader_float16
1146 shader_int8
1147 descriptor_indexing
1148 shader_input_attachment_array_dynamic_indexing
1149 shader_uniform_texel_buffer_array_dynamic_indexing
1150 shader_storage_texel_buffer_array_dynamic_indexing
1151 shader_uniform_buffer_array_non_uniform_indexing
1152 shader_sampled_image_array_non_uniform_indexing
1153 shader_storage_buffer_array_non_uniform_indexing
1154 shader_storage_image_array_non_uniform_indexing
1155 shader_input_attachment_array_non_uniform_indexing
1156 shader_uniform_texel_buffer_array_non_uniform_indexing
1157 shader_storage_texel_buffer_array_non_uniform_indexing
1158 descriptor_binding_uniform_buffer_update_after_bind
1159 descriptor_binding_sampled_image_update_after_bind
1160 descriptor_binding_storage_image_update_after_bind
1161 descriptor_binding_storage_buffer_update_after_bind
1162 descriptor_binding_uniform_texel_buffer_update_after_bind
1163 descriptor_binding_storage_texel_buffer_update_after_bind
1164 descriptor_binding_update_unused_while_pending
1165 descriptor_binding_partially_bound
1166 descriptor_binding_variable_descriptor_count
1167 runtime_descriptor_array
1168 sampler_filter_minmax
1169 scalar_block_layout
1170 imageless_framebuffer
1171 uniform_buffer_standard_layout
1172 shader_subgroup_extended_types
1173 separate_depth_stencil_layouts
1174 host_query_reset
1175 timeline_semaphore
1176 buffer_device_address
1177 buffer_device_address_capture_replay
1178 buffer_device_address_multi_device
1179 vulkan_memory_model
1180 vulkan_memory_model_device_scope
1181 vulkan_memory_model_availability_visibility_chains
1182 shader_output_viewport_index
1183 shader_output_layer
1184 subgroup_broadcast_dynamic_id
1185 }
1186 );
1187
1188 impl_feature_assemble!(
1189 physical_features_synchronization2, features_synchronization2, physical_features_synchronization2_list, features_synchronization2_list;
1190 {
1191 synchronization2
1192 }
1193 );
1194
1195 impl_feature_assemble!(
1196 physical_device_robustness2_features, device_robustness2_features, physical_device_robustness2_features_list, device_robustness2_features_list;
1197 {
1198 robust_buffer_access2
1199 robust_image_access2
1200 null_descriptor
1201 }
1202 );
1203
1204 impl_feature_assemble!(
1205 physical_features_raytracing, features_raytracing, physical_features_raytracing_list, features_raytracing_list;
1206 {
1207 ray_tracing_pipeline
1208 ray_tracing_pipeline_shader_group_handle_capture_replay
1209 ray_tracing_pipeline_shader_group_handle_capture_replay_mixed
1210 ray_tracing_pipeline_trace_rays_indirect
1211 ray_traversal_primitive_culling
1212 }
1213 );
1214
1215 impl_feature_assemble!(
1216 physical_features_acceleration_structure, features_acceleration_structure, physical_features_acceleration_structure_list, features_acceleration_structure_list;
1217 {
1218 acceleration_structure
1219 acceleration_structure_capture_replay
1220 acceleration_structure_host_commands
1221 acceleration_structure_indirect_build
1222 descriptor_binding_acceleration_structure_update_after_bind
1223 }
1224 );
1225
1226 let mut missing_features = false;
1227
1228 #[cfg(feature = "tracing")]
1229 if !features_list.is_empty() {
1230 info!("Enabling Vulkan 1.0 features:");
1231 features_list.retain(|&wanted| {
1232 let found = physical_features_list
1233 .iter()
1234 .any(|present| *present == wanted);
1235 if found {
1236 info!("- {}", wanted);
1237 true
1238 } else {
1239 #[cfg(feature = "tracing")]
1240 error!("Unable to find Vulkan 1.0 feature: {}", wanted);
1241 missing_features = true;
1242 false
1243 }
1244 });
1245 }
1246
1247 #[cfg(feature = "tracing")]
1248 if !features11_list.is_empty() {
1249 info!("Enabling Vulkan 1.1 features:");
1250 features11_list.retain(|&wanted| {
1251 let found = physical_features11_list
1252 .iter()
1253 .any(|present| *present == wanted);
1254 if found {
1255 info!("- {}", wanted);
1256 true
1257 } else {
1258 #[cfg(feature = "tracing")]
1259 error!("Unable to find Vulkan 1.1 feature: {}", wanted);
1260 missing_features = true;
1261 false
1262 }
1263 });
1264 }
1265
1266 #[cfg(feature = "tracing")]
1267 if !features12_list.is_empty() {
1268 info!("Enabling Vulkan 1.2 features:");
1269 features12_list.retain(|&wanted| {
1270 let found = physical_features12_list
1271 .iter()
1272 .any(|present| *present == wanted);
1273 if found {
1274 info!("- {}", wanted);
1275 true
1276 } else {
1277 #[cfg(feature = "tracing")]
1278 error!("Unable to find Vulkan 1.2 feature: {}", wanted);
1279 missing_features = true;
1280 false
1281 }
1282 });
1283 }
1284
1285 #[cfg(feature = "tracing")]
1286 if !features_synchronization2_list.is_empty() {
1287 info!("Enabling VK_KHR_synchronization2 features:");
1288 features_synchronization2_list.retain(|&wanted| {
1289 let found = physical_features_synchronization2_list
1290 .iter()
1291 .any(|present| *present == wanted);
1292 if found {
1293 info!("- {}", wanted);
1294 true
1295 } else {
1296 #[cfg(feature = "tracing")]
1297 error!("Unable to find VK_KHR_synchronization2 feature: {}", wanted);
1298 missing_features = true;
1299 false
1300 }
1301 });
1302 }
1303
1304 #[cfg(feature = "tracing")]
1305 if !device_robustness2_features_list.is_empty() {
1306 info!("Enabling VK_EXT_robustness2 features:");
1307 device_robustness2_features_list.retain(|&wanted| {
1308 let found = physical_device_robustness2_features_list
1309 .iter()
1310 .any(|present| *present == wanted);
1311 if found {
1312 info!("- {}", wanted);
1313 true
1314 } else {
1315 #[cfg(feature = "tracing")]
1316 error!("Unable to find VK_EXT_robustness2 feature: {}", wanted);
1317 missing_features = true;
1318 false
1319 }
1320 });
1321 }
1322
1323 #[cfg(feature = "tracing")]
1324 if !features_raytracing_list.is_empty() {
1325 info!("Enabling VK_KHR_ray_tracing_pipeline features:");
1326 features_raytracing_list.retain(|&wanted| {
1327 let found = physical_features_raytracing_list
1328 .iter()
1329 .any(|present| *present == wanted);
1330 if found {
1331 info!("- {}", wanted);
1332 true
1333 } else {
1334 #[cfg(feature = "tracing")]
1335 error!(
1336 "Unable to find VK_KHR_ray_tracing_pipeline feature: {}",
1337 wanted
1338 );
1339 missing_features = true;
1340 false
1341 }
1342 });
1343 }
1344
1345 #[cfg(feature = "tracing")]
1346 if !features_acceleration_structure_list.is_empty() {
1347 info!("Enabling VK_KHR_acceleration_structure features:");
1348 features_acceleration_structure_list.retain(|&wanted| {
1349 let found = physical_features_acceleration_structure_list
1350 .iter()
1351 .any(|present| *present == wanted);
1352 if found {
1353 info!("- {}", wanted);
1354 true
1355 } else {
1356 #[cfg(feature = "tracing")]
1357 error!(
1358 "Unable to find VK_KHR_acceleration_structure feature: {}",
1359 wanted
1360 );
1361 missing_features = true;
1362 false
1363 }
1364 });
1365 }
1366
1367 if missing_features {
1368 Err(AscheError::DeviceFeatureMissing)
1369 } else {
1370 Ok(())
1371 }
1372}
1373
1374impl Drop for Instance {
1375 fn drop(&mut self) {
1376 unsafe {
1377 #[cfg(debug_assertions)]
1378 self.raw
1379 .destroy_debug_utils_messenger_ext(Some(self.debug_messenger), None);
1380
1381 self.raw.destroy_surface_khr(Some(self.surface), None);
1382 self.raw.destroy_instance(None);
1383 };
1384 }
1385}