1#![allow(non_snake_case)]
21
22#[macro_use]
23extern crate log;
24
25#[cfg(target_os = "macos")]
26#[macro_use]
27extern crate objc;
28
29#[cfg(not(feature = "use-rtld-next"))]
30use ash::Entry;
31#[cfg(feature = "use-rtld-next")]
32type Entry = ash::EntryCustom<()>;
33use ash::{
34 extensions::{ext, khr, nv::MeshShader},
35 version::{DeviceV1_0, EntryV1_0, InstanceV1_0},
36 vk,
37};
38
39use hal::{
40 adapter,
41 device::{DeviceLost, OutOfMemory},
42 display, image, memory,
43 pso::PipelineStage,
44 queue,
45 window::{OutOfDate, PresentError, Suboptimal, SurfaceLost},
46 Features,
47};
48
49use std::{
50 borrow::Cow,
51 cmp,
52 ffi::{CStr, CString},
53 fmt, slice,
54 sync::Arc,
55 thread, unreachable,
56};
57
58mod command;
59mod conv;
60mod device;
61mod info;
62mod native;
63mod physical_device;
64mod pool;
65mod window;
66
67pub use physical_device::*;
68
69const ROUGH_MAX_ATTACHMENT_COUNT: usize = 5;
71
72pub struct RawInstance {
73 inner: ash::Instance,
74 handle_is_external: bool,
75 debug_messenger: Option<DebugMessenger>,
76 get_physical_device_properties: Option<ExtensionFn<vk::KhrGetPhysicalDeviceProperties2Fn>>,
77 display: Option<khr::Display>,
78 external_memory_capabilities: Option<ExtensionFn<vk::KhrExternalMemoryCapabilitiesFn>>,
79}
80
81pub enum DebugMessenger {
82 Utils(ext::DebugUtils, vk::DebugUtilsMessengerEXT),
83 #[allow(deprecated)] Report(ext::DebugReport, vk::DebugReportCallbackEXT),
85}
86
87impl Drop for RawInstance {
88 fn drop(&mut self) {
89 unsafe {
90 match self.debug_messenger {
91 Some(DebugMessenger::Utils(ref ext, callback)) => {
92 ext.destroy_debug_utils_messenger(callback, None)
93 }
94 #[allow(deprecated)] Some(DebugMessenger::Report(ref ext, callback)) => {
96 ext.destroy_debug_report_callback(callback, None)
97 }
98 None => {}
99 }
100
101 if !self.handle_is_external {
102 self.inner.destroy_instance(None);
103 }
104 }
105 }
106}
107
108#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
110#[repr(transparent)]
111pub struct Version(u32);
112
113impl Version {
114 pub const V1_0: Version = Self(vk::make_version(1, 0, 0));
115 pub const V1_1: Version = Self(vk::make_version(1, 1, 0));
116 pub const V1_2: Version = Self(vk::make_version(1, 2, 0));
117
118 pub const fn major(self) -> u32 {
119 vk::version_major(self.0)
120 }
121
122 pub const fn minor(self) -> u32 {
123 vk::version_minor(self.0)
124 }
125
126 pub const fn patch(self) -> u32 {
127 vk::version_patch(self.0)
128 }
129}
130
131impl fmt::Debug for Version {
132 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
133 f.debug_struct("ApiVersion")
134 .field("major", &self.major())
135 .field("minor", &self.minor())
136 .field("patch", &self.patch())
137 .finish()
138 }
139}
140
141impl Into<u32> for Version {
142 fn into(self) -> u32 {
143 self.0
144 }
145}
146
147impl Into<Version> for u32 {
148 fn into(self) -> Version {
149 Version(self)
150 }
151}
152
153pub struct Instance {
154 pub raw: Arc<RawInstance>,
155
156 pub extensions: Vec<&'static CStr>,
158
159 pub entry: Entry,
160}
161
162impl fmt::Debug for Instance {
163 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
164 fmt.write_str("Instance")
165 }
166}
167
168fn map_queue_type(flags: vk::QueueFlags) -> queue::QueueType {
169 if flags.contains(vk::QueueFlags::GRAPHICS | vk::QueueFlags::COMPUTE) {
170 queue::QueueType::General
172 } else if flags.contains(vk::QueueFlags::GRAPHICS) {
173 queue::QueueType::Graphics
175 } else if flags.contains(vk::QueueFlags::COMPUTE) {
176 queue::QueueType::Compute
178 } else if flags.contains(vk::QueueFlags::TRANSFER) {
179 queue::QueueType::Transfer
180 } else {
181 unimplemented!()
183 }
184}
185
186unsafe fn display_debug_utils_label_ext(
187 label_structs: *mut vk::DebugUtilsLabelEXT,
188 count: usize,
189) -> Option<String> {
190 if count == 0 {
191 return None;
192 }
193
194 Some(
195 slice::from_raw_parts::<vk::DebugUtilsLabelEXT>(label_structs, count)
196 .iter()
197 .flat_map(|dul_obj| {
198 dul_obj
199 .p_label_name
200 .as_ref()
201 .map(|lbl| CStr::from_ptr(lbl).to_string_lossy().into_owned())
202 })
203 .collect::<Vec<String>>()
204 .join(", "),
205 )
206}
207
208unsafe fn display_debug_utils_object_name_info_ext(
209 info_structs: *mut vk::DebugUtilsObjectNameInfoEXT,
210 count: usize,
211) -> Option<String> {
212 if count == 0 {
213 return None;
214 }
215
216 Some(
218 slice::from_raw_parts::<vk::DebugUtilsObjectNameInfoEXT>(info_structs, count)
219 .iter()
220 .map(|obj_info| {
221 let object_name = obj_info
222 .p_object_name
223 .as_ref()
224 .map(|name| CStr::from_ptr(name).to_string_lossy().into_owned());
225
226 match object_name {
227 Some(name) => format!(
228 "(type: {:?}, hndl: 0x{:x}, name: {})",
229 obj_info.object_type, obj_info.object_handle, name
230 ),
231 None => format!(
232 "(type: {:?}, hndl: 0x{:x})",
233 obj_info.object_type, obj_info.object_handle
234 ),
235 }
236 })
237 .collect::<Vec<String>>()
238 .join(", "),
239 )
240}
241
242unsafe extern "system" fn debug_utils_messenger_callback(
243 message_severity: vk::DebugUtilsMessageSeverityFlagsEXT,
244 message_type: vk::DebugUtilsMessageTypeFlagsEXT,
245 p_callback_data: *const vk::DebugUtilsMessengerCallbackDataEXT,
246 _user_data: *mut std::os::raw::c_void,
247) -> vk::Bool32 {
248 if thread::panicking() {
249 return vk::FALSE;
250 }
251 let callback_data = *p_callback_data;
252
253 let message_severity = match message_severity {
254 vk::DebugUtilsMessageSeverityFlagsEXT::ERROR => log::Level::Error,
255 vk::DebugUtilsMessageSeverityFlagsEXT::WARNING => log::Level::Warn,
256 vk::DebugUtilsMessageSeverityFlagsEXT::INFO => log::Level::Info,
257 vk::DebugUtilsMessageSeverityFlagsEXT::VERBOSE => log::Level::Trace,
258 _ => log::Level::Warn,
259 };
260 let message_type = &format!("{:?}", message_type);
261 let message_id_number: i32 = callback_data.message_id_number as i32;
262
263 let message_id_name = if callback_data.p_message_id_name.is_null() {
264 Cow::from("")
265 } else {
266 CStr::from_ptr(callback_data.p_message_id_name).to_string_lossy()
267 };
268
269 let message = if callback_data.p_message.is_null() {
270 Cow::from("")
271 } else {
272 CStr::from_ptr(callback_data.p_message).to_string_lossy()
273 };
274
275 let additional_info: [(&str, Option<String>); 3] = [
276 (
277 "queue info",
278 display_debug_utils_label_ext(
279 callback_data.p_queue_labels as *mut _,
280 callback_data.queue_label_count as usize,
281 ),
282 ),
283 (
284 "cmd buf info",
285 display_debug_utils_label_ext(
286 callback_data.p_cmd_buf_labels as *mut _,
287 callback_data.cmd_buf_label_count as usize,
288 ),
289 ),
290 (
291 "object info",
292 display_debug_utils_object_name_info_ext(
293 callback_data.p_objects as *mut _,
294 callback_data.object_count as usize,
295 ),
296 ),
297 ];
298
299 log!(message_severity, "{}\n", {
300 let mut msg = format!(
301 "\n{} [{} (0x{:x})] : {}",
302 message_type, message_id_name, message_id_number, message
303 );
304
305 for &(info_label, ref info) in additional_info.iter() {
306 if let Some(ref data) = *info {
307 msg = format!("{}\n{}: {}", msg, info_label, data);
308 }
309 }
310
311 msg
312 });
313
314 vk::FALSE
315}
316
317unsafe extern "system" fn debug_report_callback(
318 type_: vk::DebugReportFlagsEXT,
319 _: vk::DebugReportObjectTypeEXT,
320 _object: u64,
321 _location: usize,
322 _msg_code: i32,
323 layer_prefix: *const std::os::raw::c_char,
324 description: *const std::os::raw::c_char,
325 _user_data: *mut std::os::raw::c_void,
326) -> vk::Bool32 {
327 if thread::panicking() {
328 return vk::FALSE;
329 }
330
331 let level = match type_ {
332 vk::DebugReportFlagsEXT::ERROR => log::Level::Error,
333 vk::DebugReportFlagsEXT::WARNING => log::Level::Warn,
334 vk::DebugReportFlagsEXT::INFORMATION => log::Level::Info,
335 vk::DebugReportFlagsEXT::DEBUG => log::Level::Debug,
336 _ => log::Level::Warn,
337 };
338
339 let layer_prefix = CStr::from_ptr(layer_prefix).to_str().unwrap();
340 let description = CStr::from_ptr(description).to_str().unwrap();
341 log!(level, "[{}] {}", layer_prefix, description);
342 vk::FALSE
343}
344
345impl Instance {
346 pub fn required_extensions(
347 entry: &Entry,
348 driver_api_version: Version,
349 ) -> Result<Vec<&'static CStr>, hal::UnsupportedBackend> {
350 let instance_extensions = entry
351 .enumerate_instance_extension_properties()
352 .map_err(|e| {
353 info!("Unable to enumerate instance extensions: {:?}", e);
354 hal::UnsupportedBackend
355 })?;
356
357 let mut extensions: Vec<&'static CStr> = Vec::new();
359 extensions.push(khr::Surface::name());
360
361 if cfg!(all(
363 unix,
364 not(target_os = "android"),
365 not(target_os = "macos")
366 )) {
367 extensions.push(khr::XlibSurface::name());
368 extensions.push(khr::XcbSurface::name());
369 extensions.push(khr::WaylandSurface::name());
370 }
371 if cfg!(target_os = "android") {
372 extensions.push(khr::AndroidSurface::name());
373 }
374 if cfg!(target_os = "windows") {
375 extensions.push(khr::Win32Surface::name());
376 }
377 if cfg!(target_os = "macos") {
378 extensions.push(ash::extensions::mvk::MacOSSurface::name());
379 }
380
381 extensions.push(ext::DebugUtils::name());
382 if cfg!(debug_assertions) {
383 #[allow(deprecated)]
384 extensions.push(ext::DebugReport::name());
385 }
386
387 extensions.push(vk::KhrGetPhysicalDeviceProperties2Fn::name());
388
389 if driver_api_version == Version::V1_0 {
391 extensions.push(vk::KhrStorageBufferStorageClassFn::name());
392 }
393
394 extensions.push(vk::ExtDisplaySurfaceCounterFn::name());
395 extensions.push(khr::Display::name());
396
397 if driver_api_version < Version::V1_1 {
398 extensions.push(vk::KhrExternalMemoryCapabilitiesFn::name());
399 }
400
401 if driver_api_version == Version::V1_0 {
403 extensions.push(vk::KhrStorageBufferStorageClassFn::name());
404 }
405
406 extensions.retain(|&ext| {
408 if instance_extensions
409 .iter()
410 .find(|inst_ext| unsafe { CStr::from_ptr(inst_ext.extension_name.as_ptr()) == ext })
411 .is_some()
412 {
413 true
414 } else {
415 info!("Unable to find extension: {}", ext.to_string_lossy());
416 false
417 }
418 });
419 Ok(extensions)
420 }
421
422 pub fn required_layers(entry: &Entry) -> Result<Vec<&'static CStr>, hal::UnsupportedBackend> {
423 let instance_layers = entry.enumerate_instance_layer_properties().map_err(|e| {
424 info!("Unable to enumerate instance layers: {:?}", e);
425 hal::UnsupportedBackend
426 })?;
427
428 let mut layers: Vec<&'static CStr> = Vec::new();
430 if cfg!(debug_assertions) {
431 layers.push(CStr::from_bytes_with_nul(b"VK_LAYER_KHRONOS_validation\0").unwrap());
432 }
433
434 layers.retain(|&layer| {
436 if instance_layers
437 .iter()
438 .find(|inst_layer| unsafe {
439 CStr::from_ptr(inst_layer.layer_name.as_ptr()) == layer
440 })
441 .is_some()
442 {
443 true
444 } else {
445 warn!("Unable to find layer: {}", layer.to_string_lossy());
446 false
447 }
448 });
449 Ok(layers)
450 }
451
452 pub unsafe fn from_raw(
459 entry: Entry,
460 raw_instance: ash::Instance,
461 driver_api_version: Version,
462 extensions: Vec<&'static CStr>,
463 ) -> Result<Self, hal::UnsupportedBackend> {
464 Instance::inner_create(entry, raw_instance, true, driver_api_version, extensions)
465 }
466
467 fn inner_create(
468 entry: Entry,
469 instance: ash::Instance,
470 handle_is_external: bool,
471 driver_api_version: Version,
472 extensions: Vec<&'static CStr>,
473 ) -> Result<Self, hal::UnsupportedBackend> {
474 if driver_api_version == Version::V1_0
475 && !extensions.contains(&vk::KhrStorageBufferStorageClassFn::name())
476 {
477 warn!("Unable to create Vulkan instance. Required VK_KHR_storage_buffer_storage_class extension is not supported");
478 return Err(hal::UnsupportedBackend);
479 }
480
481 let instance_extensions = entry
482 .enumerate_instance_extension_properties()
483 .map_err(|e| {
484 info!("Unable to enumerate instance extensions: {:?}", e);
485 hal::UnsupportedBackend
486 })?;
487
488 let get_physical_device_properties = if driver_api_version >= Version::V1_1 {
489 Some(ExtensionFn::Promoted)
490 } else {
491 extensions
492 .iter()
493 .find(|&&ext| ext == vk::KhrGetPhysicalDeviceProperties2Fn::name())
494 .map(|_| {
495 ExtensionFn::Extension(vk::KhrGetPhysicalDeviceProperties2Fn::load(
496 |name| unsafe {
497 std::mem::transmute(
498 entry.get_instance_proc_addr(instance.handle(), name.as_ptr()),
499 )
500 },
501 ))
502 })
503 };
504
505 let display = extensions
506 .iter()
507 .find(|&&ext| ext == khr::Display::name())
508 .map(|_| khr::Display::new(&entry, &instance));
509
510 let external_memory_capabilities = if driver_api_version >= Version::V1_1 {
511 Some(ExtensionFn::Promoted)
512 } else {
513 extensions
514 .iter()
515 .find(|&&ext| ext == vk::KhrExternalMemoryCapabilitiesFn::name())
516 .map(|_| {
517 ExtensionFn::Extension(vk::KhrExternalMemoryCapabilitiesFn::load(
518 |name| unsafe {
519 std::mem::transmute(
520 entry.get_instance_proc_addr(instance.handle(), name.as_ptr()),
521 )
522 },
523 ))
524 })
525 };
526
527 #[allow(deprecated)] let debug_messenger = {
529 if instance_extensions.iter().any(|props| unsafe {
531 CStr::from_ptr(props.extension_name.as_ptr()) == ext::DebugUtils::name()
532 }) {
533 let ext = ext::DebugUtils::new(&entry, &instance);
534 let info = vk::DebugUtilsMessengerCreateInfoEXT::builder()
535 .flags(vk::DebugUtilsMessengerCreateFlagsEXT::empty())
536 .message_severity(vk::DebugUtilsMessageSeverityFlagsEXT::all())
537 .message_type(vk::DebugUtilsMessageTypeFlagsEXT::all())
538 .pfn_user_callback(Some(debug_utils_messenger_callback));
539 let handle = unsafe { ext.create_debug_utils_messenger(&info, None) }.unwrap();
540 Some(DebugMessenger::Utils(ext, handle))
541 } else if cfg!(debug_assertions)
542 && instance_extensions.iter().any(|props| unsafe {
543 CStr::from_ptr(props.extension_name.as_ptr()) == ext::DebugReport::name()
544 })
545 {
546 let ext = ext::DebugReport::new(&entry, &instance);
547 let info = vk::DebugReportCallbackCreateInfoEXT::builder()
548 .flags(vk::DebugReportFlagsEXT::all())
549 .pfn_callback(Some(debug_report_callback));
550 let handle = unsafe { ext.create_debug_report_callback(&info, None) }.unwrap();
551 Some(DebugMessenger::Report(ext, handle))
552 } else {
553 None
554 }
555 };
556
557 Ok(Instance {
558 raw: Arc::new(RawInstance {
559 inner: instance,
560 handle_is_external,
561 debug_messenger,
562 get_physical_device_properties,
563 display,
564 external_memory_capabilities,
565 }),
566 extensions,
567 entry,
568 })
569 }
570
571 pub unsafe fn adapter_from_raw(
574 &self,
575 raw_physical_device: vk::PhysicalDevice,
576 ) -> adapter::Adapter<Backend> {
577 physical_device::load_adapter(&self.raw, raw_physical_device)
578 }
579}
580
581impl hal::Instance<Backend> for Instance {
582 fn create(name: &str, version: u32) -> Result<Self, hal::UnsupportedBackend> {
583 #[cfg(not(feature = "use-rtld-next"))]
584 let entry = match unsafe { Entry::new() } {
585 Ok(entry) => entry,
586 Err(err) => {
587 info!("Missing Vulkan entry points: {:?}", err);
588 return Err(hal::UnsupportedBackend);
589 }
590 };
591
592 #[cfg(feature = "use-rtld-next")]
593 let entry = Entry::new_custom((), |_, name| unsafe {
594 libc::dlsym(libc::RTLD_NEXT, name.as_ptr())
595 });
596
597 let driver_api_version = match entry.try_enumerate_instance_version() {
598 Ok(Some(version)) => version.into(),
600
601 Ok(None) => Version::V1_0,
603
604 Err(err) if err == vk::Result::ERROR_OUT_OF_HOST_MEMORY => {
606 warn!("vkEnumerateInstanceVersion returned VK_ERROR_OUT_OF_HOST_MEMORY");
607 return Err(hal::UnsupportedBackend);
608 }
609
610 Err(_) => unreachable!(),
611 };
612
613 let app_name = CString::new(name).unwrap();
614 let app_info = vk::ApplicationInfo::builder()
615 .application_name(app_name.as_c_str())
616 .application_version(version)
617 .engine_name(CStr::from_bytes_with_nul(b"gfx-rs\0").unwrap())
618 .engine_version(1)
619 .api_version({
620 cmp::min(driver_api_version, {
622 Version::V1_2
633 })
634 .into()
635 });
636
637 let extensions = Instance::required_extensions(&entry, driver_api_version)?;
638
639 let layers = Instance::required_layers(&entry)?;
640
641 let instance = {
642 let str_pointers = layers
643 .iter()
644 .chain(extensions.iter())
645 .map(|&s| {
646 s.as_ptr()
648 })
649 .collect::<Vec<_>>();
650
651 let create_info = vk::InstanceCreateInfo::builder()
652 .flags(vk::InstanceCreateFlags::empty())
653 .application_info(&app_info)
654 .enabled_layer_names(&str_pointers[..layers.len()])
655 .enabled_extension_names(&str_pointers[layers.len()..]);
656
657 unsafe { entry.create_instance(&create_info, None) }.map_err(|e| {
658 warn!("Unable to create Vulkan instance: {:?}", e);
659 hal::UnsupportedBackend
660 })?
661 };
662 Instance::inner_create(entry, instance, false, driver_api_version, extensions)
663 }
664
665 fn enumerate_adapters(&self) -> Vec<adapter::Adapter<Backend>> {
666 let devices = match unsafe { self.raw.inner.enumerate_physical_devices() } {
667 Ok(devices) => devices,
668 Err(err) => {
669 error!("Could not enumerate physical devices! {}", err);
670 vec![]
671 }
672 };
673
674 devices
675 .into_iter()
676 .map(|device| physical_device::load_adapter(&self.raw, device))
677 .collect()
678 }
679
680 unsafe fn create_surface(
681 &self,
682 has_handle: &impl raw_window_handle::HasRawWindowHandle,
683 ) -> Result<window::Surface, hal::window::InitError> {
684 use raw_window_handle::RawWindowHandle;
685
686 match has_handle.raw_window_handle() {
687 #[cfg(all(
688 unix,
689 not(target_os = "android"),
690 not(target_os = "macos"),
691 not(target_os = "solaris")
692 ))]
693 RawWindowHandle::Wayland(handle)
694 if self.extensions.contains(&khr::WaylandSurface::name()) =>
695 {
696 Ok(self.create_surface_from_wayland(handle.display, handle.surface))
697 }
698 #[cfg(all(
699 unix,
700 not(target_os = "android"),
701 not(target_os = "macos"),
702 not(target_os = "solaris")
703 ))]
704 RawWindowHandle::Xlib(handle)
705 if self.extensions.contains(&khr::XlibSurface::name()) =>
706 {
707 Ok(self.create_surface_from_xlib(handle.display as *mut _, handle.window))
708 }
709 #[cfg(all(
710 unix,
711 not(target_os = "android"),
712 not(target_os = "macos"),
713 not(target_os = "ios")
714 ))]
715 RawWindowHandle::Xcb(handle) if self.extensions.contains(&khr::XcbSurface::name()) => {
716 Ok(self.create_surface_from_xcb(handle.connection as *mut _, handle.window))
717 }
718 #[cfg(target_os = "android")]
719 RawWindowHandle::Android(handle) => {
720 Ok(self.create_surface_android(handle.a_native_window))
721 }
722 #[cfg(windows)]
723 RawWindowHandle::Windows(handle) => {
724 use winapi::um::libloaderapi::GetModuleHandleW;
725
726 let hinstance = GetModuleHandleW(std::ptr::null());
727 Ok(self.create_surface_from_hwnd(hinstance as *mut _, handle.hwnd))
728 }
729 #[cfg(target_os = "macos")]
730 RawWindowHandle::MacOS(handle) => Ok(self.create_surface_from_ns_view(handle.ns_view)),
731 _ => Err(hal::window::InitError::UnsupportedWindowHandle),
732 }
733 }
734
735 unsafe fn destroy_surface(&self, surface: window::Surface) {
736 surface
737 .raw
738 .functor
739 .destroy_surface(surface.raw.handle, None);
740 }
741
742 unsafe fn create_display_plane_surface(
743 &self,
744 display_plane: &hal::display::DisplayPlane<Backend>,
745 plane_stack_index: u32,
746 transformation: hal::display::SurfaceTransform,
747 alpha: hal::display::DisplayPlaneAlpha,
748 image_extent: hal::window::Extent2D,
749 ) -> Result<window::Surface, hal::display::DisplayPlaneSurfaceError> {
750 let display_extension = match &self.raw.display {
751 Some(display_extension) => display_extension,
752 None => {
753 error!("Direct display feature not supported");
754 return Err(display::DisplayPlaneSurfaceError::UnsupportedFeature);
755 }
756 };
757 let surface_transform_flags = hal::display::SurfaceTransformFlags::from(transformation);
758 let vk_surface_transform_flags =
759 vk::SurfaceTransformFlagsKHR::from_raw(surface_transform_flags.bits());
760
761 let display_surface_ci = {
762 let builder = vk::DisplaySurfaceCreateInfoKHR::builder()
763 .display_mode(display_plane.display_mode.handle.0)
764 .plane_index(display_plane.plane.handle)
765 .plane_stack_index(plane_stack_index)
766 .image_extent(vk::Extent2D {
767 width: image_extent.width,
768 height: image_extent.height,
769 })
770 .transform(vk_surface_transform_flags);
771
772 match alpha {
773 hal::display::DisplayPlaneAlpha::Opaque => {
774 builder.alpha_mode(vk::DisplayPlaneAlphaFlagsKHR::OPAQUE)
775 }
776 hal::display::DisplayPlaneAlpha::Global(value) => builder
777 .alpha_mode(vk::DisplayPlaneAlphaFlagsKHR::GLOBAL)
778 .global_alpha(value),
779 hal::display::DisplayPlaneAlpha::PerPixel => {
780 builder.alpha_mode(vk::DisplayPlaneAlphaFlagsKHR::PER_PIXEL)
781 }
782 hal::display::DisplayPlaneAlpha::PerPixelPremultiplied => {
783 builder.alpha_mode(vk::DisplayPlaneAlphaFlagsKHR::PER_PIXEL_PREMULTIPLIED)
784 }
785 }
786 .build()
787 };
788
789 let surface = match display_extension
790 .create_display_plane_surface(&display_surface_ci, None)
791 {
792 Ok(surface) => surface,
793 Err(vk::Result::ERROR_OUT_OF_HOST_MEMORY) => return Err(OutOfMemory::Host.into()),
794 Err(vk::Result::ERROR_OUT_OF_DEVICE_MEMORY) => return Err(OutOfMemory::Device.into()),
795 err => panic!(
796 "Unexpected error on `create_display_plane_surface`: {:#?}",
797 err
798 ),
799 };
800
801 Ok(self.create_surface_from_vk_surface_khr(surface))
802 }
803}
804
805#[derive(Debug, Clone)]
806pub struct QueueFamily {
807 properties: vk::QueueFamilyProperties,
808 device: vk::PhysicalDevice,
809 index: u32,
810}
811
812impl queue::QueueFamily for QueueFamily {
813 fn queue_type(&self) -> queue::QueueType {
814 map_queue_type(self.properties.queue_flags)
815 }
816 fn max_queues(&self) -> usize {
817 self.properties.queue_count as _
818 }
819 fn id(&self) -> queue::QueueFamilyId {
820 queue::QueueFamilyId(self.index as _)
821 }
822 fn supports_sparse_binding(&self) -> bool {
823 self.properties
824 .queue_flags
825 .contains(vk::QueueFlags::SPARSE_BINDING)
826 }
827}
828
829struct DeviceExtensionFunctions {
830 mesh_shaders: Option<ExtensionFn<MeshShader>>,
831 draw_indirect_count: Option<ExtensionFn<khr::DrawIndirectCount>>,
832 display_control: Option<vk::ExtDisplayControlFn>,
833 memory_requirements2: Option<ExtensionFn<vk::KhrGetMemoryRequirements2Fn>>,
834 dedicated_allocation: Option<ExtensionFn<()>>,
836 external_memory: Option<ExtensionFn<()>>,
838 external_memory_host: Option<vk::ExtExternalMemoryHostFn>,
839 #[cfg(windows)]
840 external_memory_win32: Option<vk::KhrExternalMemoryWin32Fn>,
841 #[cfg(unix)]
842 external_memory_fd: Option<khr::ExternalMemoryFd>,
843 #[cfg(any(target_os = "linux", target_os = "android"))]
844 external_memory_dma_buf: Option<()>,
846 #[cfg(any(target_os = "linux", target_os = "android"))]
847 image_drm_format_modifier: Option<vk::ExtImageDrmFormatModifierFn>,
848}
849
850enum ExtensionFn<T> {
852 Extension(T),
854 Promoted,
856}
857
858impl<T> ExtensionFn<T> {
859 fn unwrap_extension(&self) -> &T {
861 if let ExtensionFn::Extension(t) = self {
862 t
863 } else {
864 panic!()
865 }
866 }
867}
868
869#[doc(hidden)]
870pub struct RawDevice {
871 raw: ash::Device,
872 handle_is_external: bool,
873 features: Features,
874 instance: Arc<RawInstance>,
875 extension_fns: DeviceExtensionFunctions,
876 flip_y_requires_shift: bool,
880 imageless_framebuffers: bool,
881 image_view_usage: bool,
882 timestamp_period: f32,
883}
884
885impl fmt::Debug for RawDevice {
886 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
887 write!(f, "RawDevice") }
889}
890impl Drop for RawDevice {
891 fn drop(&mut self) {
892 if !self.handle_is_external {
893 unsafe {
894 self.raw.destroy_device(None);
895 }
896 }
897 }
898}
899
900impl RawDevice {
901 fn debug_messenger(&self) -> Option<&DebugMessenger> {
902 self.instance.debug_messenger.as_ref()
903 }
904
905 fn map_viewport(&self, rect: &hal::pso::Viewport) -> vk::Viewport {
906 let flip_y = self.features.contains(hal::Features::NDC_Y_UP);
907 let shift_y = flip_y && self.flip_y_requires_shift;
908 conv::map_viewport(rect, flip_y, shift_y)
909 }
910
911 unsafe fn set_object_name(
912 &self,
913 object_type: vk::ObjectType,
914 object: impl vk::Handle,
915 name: &str,
916 ) {
917 let instance = &self.instance;
918 if let Some(DebugMessenger::Utils(ref debug_utils_ext, _)) = instance.debug_messenger {
919 let mut buffer: [u8; 64] = [0u8; 64];
922 let buffer_vec: Vec<u8>;
923
924 let name_cstr = if name.len() < 64 {
926 std::ptr::copy_nonoverlapping(name.as_ptr(), buffer.as_mut_ptr(), name.len());
928 buffer[name.len()] = 0;
930 CStr::from_bytes_with_nul(&buffer[..name.len() + 1]).unwrap()
931 } else {
932 buffer_vec = name
935 .as_bytes()
936 .iter()
937 .cloned()
938 .chain(std::iter::once(0))
939 .collect::<Vec<u8>>();
940 CStr::from_bytes_with_nul(&buffer_vec).unwrap()
941 };
942 let _result = debug_utils_ext.debug_utils_set_object_name(
943 self.raw.handle(),
944 &vk::DebugUtilsObjectNameInfoEXT::builder()
945 .object_type(object_type)
946 .object_handle(object.as_raw())
947 .object_name(name_cstr),
948 );
949 }
950 }
951}
952
953pub type RawCommandQueue = Arc<vk::Queue>;
955
956pub struct Queue {
957 raw: RawCommandQueue,
958 device: Arc<RawDevice>,
959 swapchain_fn: khr::Swapchain,
960}
961
962impl fmt::Debug for Queue {
963 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
964 fmt.write_str("Queue")
965 }
966}
967
968impl queue::Queue<Backend> for Queue {
969 unsafe fn submit<'a, Ic, Iw, Is>(
970 &mut self,
971 command_buffers: Ic,
972 wait_semaphores: Iw,
973 signal_semaphores: Is,
974 fence: Option<&mut native::Fence>,
975 ) where
976 Ic: Iterator<Item = &'a command::CommandBuffer>,
977 Iw: Iterator<Item = (&'a native::Semaphore, PipelineStage)>,
978 Is: Iterator<Item = &'a native::Semaphore>,
979 {
980 let mut waits = Vec::new();
982 let mut stages = Vec::new();
983
984 let buffers = command_buffers.map(|cmd| cmd.raw).collect::<Vec<_>>();
985 for (semaphore, stage) in wait_semaphores {
986 waits.push(semaphore.0);
987 stages.push(conv::map_pipeline_stage(stage));
988 }
989 let signals = signal_semaphores
990 .map(|semaphore| semaphore.0)
991 .collect::<Vec<_>>();
992
993 let mut info = vk::SubmitInfo::builder()
994 .wait_semaphores(&waits)
995 .command_buffers(&buffers)
996 .signal_semaphores(&signals);
997 if !stages.is_empty() {
999 info = info.wait_dst_stage_mask(&stages);
1000 }
1001
1002 let fence_raw = fence.map(|fence| fence.0).unwrap_or(vk::Fence::null());
1003
1004 let result = self.device.raw.queue_submit(*self.raw, &[*info], fence_raw);
1005 if let Err(e) = result {
1006 error!("Submit resulted in {:?}", e);
1007 }
1008 }
1009
1010 unsafe fn bind_sparse<'a, Iw, Is, Ibi, Ib, Iii, Io, Ii>(
1011 &mut self,
1012 wait_semaphores: Iw,
1013 signal_semaphores: Is,
1014 buffer_memory_binds: Ib,
1015 image_opaque_memory_binds: Io,
1016 image_memory_binds: Ii,
1017 device: &Device,
1018 fence: Option<&native::Fence>,
1019 ) where
1020 Ibi: Iterator<Item = &'a memory::SparseBind<&'a native::Memory>>,
1021 Ib: Iterator<Item = (&'a mut native::Buffer, Ibi)>,
1022 Iii: Iterator<Item = &'a memory::SparseImageBind<&'a native::Memory>>,
1023 Io: Iterator<Item = (&'a mut native::Image, Ibi)>,
1024 Ii: Iterator<Item = (&'a mut native::Image, Iii)>,
1025 Iw: Iterator<Item = &'a native::Semaphore>,
1026 Is: Iterator<Item = &'a native::Semaphore>,
1027 {
1028 let mut waits = Vec::new();
1030
1031 for semaphore in wait_semaphores {
1032 waits.push(semaphore.0);
1033 }
1034 let signals = signal_semaphores
1035 .map(|semaphore| semaphore.0)
1036 .collect::<Vec<_>>();
1037
1038 let mut buffer_memory_binds_vec = Vec::new();
1039 let mut buffer_binds = buffer_memory_binds
1040 .map(|(buffer, bind_iter)| {
1041 let binds_before = buffer_memory_binds_vec.len();
1042 buffer_memory_binds_vec.extend(bind_iter.into_iter().map(|bind| {
1043 let mut bind_builder = vk::SparseMemoryBind::builder()
1044 .resource_offset(bind.resource_offset as u64)
1045 .size(bind.size as u64);
1046 if let Some((memory, memory_offset)) = bind.memory {
1047 bind_builder = bind_builder.memory(memory.raw);
1048 bind_builder = bind_builder.memory_offset(memory_offset as u64);
1049 }
1050
1051 bind_builder.build()
1052 }));
1053
1054 vk::SparseBufferMemoryBindInfo {
1055 buffer: buffer.raw,
1056 bind_count: (buffer_memory_binds_vec.len() - binds_before) as u32,
1057 p_binds: std::ptr::null(),
1058 }
1059 })
1060 .collect::<Vec<_>>();
1061 buffer_binds.iter_mut().fold(0u32, |idx, bind| {
1063 (*bind).p_binds = &buffer_memory_binds_vec[idx as usize];
1064 idx + bind.bind_count
1065 });
1066
1067 let mut image_opaque_memory_binds_vec = Vec::new();
1068 let mut image_opaque_binds = image_opaque_memory_binds
1069 .map(|(image, bind_iter)| {
1070 let binds_before = image_opaque_memory_binds_vec.len();
1071 image_opaque_memory_binds_vec.extend(bind_iter.into_iter().map(|bind| {
1072 let mut bind_builder = vk::SparseMemoryBind::builder()
1073 .resource_offset(bind.resource_offset as u64)
1074 .size(bind.size as u64);
1075 if let Some((memory, memory_offset)) = bind.memory {
1076 bind_builder = bind_builder.memory(memory.raw);
1077 bind_builder = bind_builder.memory_offset(memory_offset as u64);
1078 }
1079
1080 bind_builder.build()
1081 }));
1082
1083 vk::SparseImageOpaqueMemoryBindInfo {
1084 image: image.raw,
1085 bind_count: (image_opaque_memory_binds_vec.len() - binds_before) as u32,
1086 p_binds: std::ptr::null(),
1087 }
1088 })
1089 .collect::<Vec<_>>();
1090 image_opaque_binds.iter_mut().fold(0u32, |idx, bind| {
1092 (*bind).p_binds = &image_opaque_memory_binds_vec[idx as usize];
1093 idx + bind.bind_count
1094 });
1095
1096 let mut image_memory_binds_vec = Vec::new();
1097 let mut image_binds = image_memory_binds
1098 .map(|(image, bind_iter)| {
1099 let binds_before = image_memory_binds_vec.len();
1100 image_memory_binds_vec.extend(bind_iter.into_iter().map(|bind| {
1101 let mut bind_builder = vk::SparseImageMemoryBind::builder()
1102 .subresource(conv::map_subresource(&bind.subresource))
1103 .offset(conv::map_offset(bind.offset))
1104 .extent(conv::map_extent(bind.extent));
1105 if let Some((memory, memory_offset)) = bind.memory {
1106 bind_builder = bind_builder.memory(memory.raw);
1107 bind_builder = bind_builder.memory_offset(memory_offset as u64);
1108 }
1109
1110 bind_builder.build()
1111 }));
1112
1113 vk::SparseImageMemoryBindInfo {
1114 image: image.raw,
1115 bind_count: (image_memory_binds_vec.len() - binds_before) as u32,
1116 p_binds: std::ptr::null(),
1117 }
1118 })
1119 .collect::<Vec<_>>();
1120 image_binds.iter_mut().fold(0u32, |idx, bind| {
1122 (*bind).p_binds = &image_memory_binds_vec[idx as usize];
1123 idx + bind.bind_count
1124 });
1125
1126 let info = vk::BindSparseInfo::builder()
1127 .wait_semaphores(&waits)
1128 .signal_semaphores(&signals)
1129 .buffer_binds(&buffer_binds)
1130 .image_opaque_binds(&image_opaque_binds)
1131 .image_binds(&image_binds);
1132
1133 let info = info.build();
1134 let fence_raw = fence.map(|fence| fence.0).unwrap_or(vk::Fence::null());
1135
1136 assert_eq!(
1138 vk::Result::SUCCESS,
1139 device
1140 .shared
1141 .raw
1142 .fp_v1_0()
1143 .queue_bind_sparse(*self.raw, 1, &info, fence_raw)
1144 );
1145 }
1146
1147 unsafe fn present(
1148 &mut self,
1149 surface: &mut window::Surface,
1150 image: window::SurfaceImage,
1151 wait_semaphore: Option<&mut native::Semaphore>,
1152 ) -> Result<Option<Suboptimal>, PresentError> {
1153 let ssc = surface.swapchain.as_ref().unwrap();
1154 let wait_semaphore = if let Some(wait_semaphore) = wait_semaphore {
1155 wait_semaphore.0
1156 } else {
1157 let signals = &[ssc.semaphore.0];
1158 let submit_info = vk::SubmitInfo::builder().signal_semaphores(signals);
1159 self.device
1160 .raw
1161 .queue_submit(*self.raw, &[*submit_info], vk::Fence::null())
1162 .unwrap();
1163 ssc.semaphore.0
1164 };
1165
1166 let wait_semaphores = &[wait_semaphore];
1167 let swapchains = &[ssc.swapchain.raw];
1168 let image_indices = &[image.index];
1169 let present_info = vk::PresentInfoKHR::builder()
1170 .wait_semaphores(wait_semaphores)
1171 .swapchains(swapchains)
1172 .image_indices(image_indices);
1173
1174 match self.swapchain_fn.queue_present(*self.raw, &present_info) {
1175 Ok(false) => Ok(None),
1176 Ok(true) => Ok(Some(Suboptimal)),
1177 Err(vk::Result::ERROR_OUT_OF_HOST_MEMORY) => Err(OutOfMemory::Host.into()),
1178 Err(vk::Result::ERROR_OUT_OF_DEVICE_MEMORY) => Err(OutOfMemory::Device.into()),
1179 Err(vk::Result::ERROR_DEVICE_LOST) => Err(DeviceLost.into()),
1180 Err(vk::Result::ERROR_OUT_OF_DATE_KHR) => Err(OutOfDate.into()),
1181 Err(vk::Result::ERROR_SURFACE_LOST_KHR) => Err(SurfaceLost.into()),
1182 _ => panic!("Failed to present frame"),
1183 }
1184 }
1185
1186 fn wait_idle(&mut self) -> Result<(), OutOfMemory> {
1187 match unsafe { self.device.raw.queue_wait_idle(*self.raw) } {
1188 Ok(()) => Ok(()),
1189 Err(vk::Result::ERROR_OUT_OF_HOST_MEMORY) => Err(OutOfMemory::Host),
1190 Err(vk::Result::ERROR_OUT_OF_DEVICE_MEMORY) => Err(OutOfMemory::Device),
1191 Err(_) => unreachable!(),
1192 }
1193 }
1194
1195 fn timestamp_period(&self) -> f32 {
1196 self.device.timestamp_period
1197 }
1198}
1199
1200#[derive(Debug)]
1201pub struct Device {
1202 shared: Arc<RawDevice>,
1203 vendor_id: u32,
1204 valid_ash_memory_types: u32,
1205 render_doc: gfx_renderdoc::RenderDoc,
1206 #[cfg(feature = "naga")]
1207 naga_options: naga::back::spv::Options,
1208}
1209
1210#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
1211pub enum Backend {}
1212impl hal::Backend for Backend {
1213 type Instance = Instance;
1214 type PhysicalDevice = PhysicalDevice;
1215 type Device = Device;
1216 type Surface = window::Surface;
1217
1218 type QueueFamily = QueueFamily;
1219 type Queue = Queue;
1220 type CommandBuffer = command::CommandBuffer;
1221
1222 type Memory = native::Memory;
1223 type CommandPool = pool::RawCommandPool;
1224
1225 type ShaderModule = native::ShaderModule;
1226 type RenderPass = native::RenderPass;
1227 type Framebuffer = native::Framebuffer;
1228
1229 type Buffer = native::Buffer;
1230 type BufferView = native::BufferView;
1231 type Image = native::Image;
1232 type ImageView = native::ImageView;
1233 type Sampler = native::Sampler;
1234
1235 type ComputePipeline = native::ComputePipeline;
1236 type GraphicsPipeline = native::GraphicsPipeline;
1237 type PipelineLayout = native::PipelineLayout;
1238 type PipelineCache = native::PipelineCache;
1239 type DescriptorSetLayout = native::DescriptorSetLayout;
1240 type DescriptorPool = native::DescriptorPool;
1241 type DescriptorSet = native::DescriptorSet;
1242
1243 type Fence = native::Fence;
1244 type Semaphore = native::Semaphore;
1245 type Event = native::Event;
1246 type QueryPool = native::QueryPool;
1247
1248 type Display = native::Display;
1249 type DisplayMode = native::DisplayMode;
1250}