gfx_backend_vulkan/
lib.rs

1/*!
2# Vulkan backend internals.
3
4## Stack memory
5
6Most of the code just passes the data through. The only problem
7that affects all the pieces is related to memory allocation:
8Vulkan expects slices, but the API gives us `Iterator`.
9So we end up using a lot of `inplace_it` to get things collected on stack.
10
11## Framebuffers
12
13One part that has actual logic is related to framebuffers. HAL is modelled
14after image-less framebuffers. If the the Vulkan implementation supports it,
15we map it 1:1, and everything is great. If it doesn't expose
16`KHR_imageless_framebuffer`, however, than we have to keep all the created
17framebuffers internally in an internally-synchronized map, per `B::Framebuffer`.
18!*/
19
20#![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
69// Sets up the maximum count we expect in most cases, but maybe not all of them.
70const 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)] // `DebugReport`
84    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)] // `DebugReport`
95                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/// Helper wrapper around `vk::make_version`.
109#[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    /// Supported extensions of this instance.
157    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        // TRANSFER_BIT optional
171        queue::QueueType::General
172    } else if flags.contains(vk::QueueFlags::GRAPHICS) {
173        // TRANSFER_BIT optional
174        queue::QueueType::Graphics
175    } else if flags.contains(vk::QueueFlags::COMPUTE) {
176        // TRANSFER_BIT optional
177        queue::QueueType::Compute
178    } else if flags.contains(vk::QueueFlags::TRANSFER) {
179        queue::QueueType::Transfer
180    } else {
181        // TODO: present only queues?
182        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    //TODO: use color field of vk::DebugUtilsLabelExt in a meaningful way?
217    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        // Check our extensions against the available extensions
358        let mut extensions: Vec<&'static CStr> = Vec::new();
359        extensions.push(khr::Surface::name());
360
361        // Platform-specific WSI extensions
362        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        // VK_KHR_storage_buffer_storage_class required for `Naga` on Vulkan 1.0 devices
390        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        // VK_KHR_storage_buffer_storage_class required for `Naga` on Vulkan 1.0 devices
402        if driver_api_version == Version::V1_0 {
403            extensions.push(vk::KhrStorageBufferStorageClassFn::name());
404        }
405
406        // Only keep available extensions.
407        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        // Check requested layers against the available layers
429        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        // Only keep available layers.
435        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    /// # Safety
453    /// `raw_instance` must be created using at least the extensions provided by `Instance::required_extensions()`
454    /// and the layers provided by `Instance::required_extensions()`.
455    /// `driver_api_version` must match the version used to create `raw_instance`.
456    /// `extensions` must match the extensions used to create `raw_instance`.
457    /// `raw_instance` must be manually destroyed *after* gfx-hal Instance has been dropped.
458    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)] // `DebugReport`
528        let debug_messenger = {
529            // make sure VK_EXT_debug_utils is available
530            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    /// # Safety
572    /// `raw_physical_device` must be created from `self` (or from the inner raw handle)
573    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            // Vulkan 1.1+
599            Ok(Some(version)) => version.into(),
600
601            // Vulkan 1.0
602            Ok(None) => Version::V1_0,
603
604            // Ignore out of memory since it's unlikely to happen and `Instance::create` doesn't have a way to express it in the return value.
605            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                // Pick the latest API version available, but don't go later than the SDK version used by `gfx_backend_vulkan`.
621                cmp::min(driver_api_version, {
622                    // This is the max Vulkan API version supported by `gfx_backend_vulkan`.
623                    //
624                    // If we want to increment this, there are some things that must be done first:
625                    //  - Audit the behavioral differences between the previous and new API versions.
626                    //  - Audit all extensions used by this backend:
627                    //    - If any were promoted in the new API version and the behavior has changed, we must handle the new behavior in addition to the old behavior.
628                    //    - If any were obsoleted in the new API version, we must implement a fallback for the new API version
629                    //    - If any are non-KHR-vendored, we must ensure the new behavior is still correct (since backwards-compatibility is not guaranteed).
630                    //
631                    // TODO: This should be replaced by `vk::HEADER_VERSION_COMPLETE` (added in `ash@6f488cd`) and this comment moved to either `README.md` or `Cargo.toml`.
632                    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                    // Safe because `layers` and `extensions` entries have static lifetime.
647                    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    // The extension does not have its own functions.
835    dedicated_allocation: Option<ExtensionFn<()>>,
836    // The extension does not have its own functions.
837    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    // The extension does not have its own functions.
845    external_memory_dma_buf: Option<()>,
846    #[cfg(any(target_os = "linux", target_os = "android"))]
847    image_drm_format_modifier: Option<vk::ExtImageDrmFormatModifierFn>,
848}
849
850// TODO there's no reason why this can't be unified--the function pointers should all be the same--it's not clear how to do this with `ash`.
851enum ExtensionFn<T> {
852    /// The loaded function pointer struct for an extension.
853    Extension(T),
854    /// The extension was promoted to a core version of Vulkan and the functions on `ash`'s `DeviceV1_x` traits should be used.
855    Promoted,
856}
857
858impl<T> ExtensionFn<T> {
859    /// Expect `self` to be `ExtensionFn::Extension` and return the inner value.
860    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    /// The `hal::Features::NDC_Y_UP` flag is implemented with either `VK_AMD_negative_viewport_height` or `VK_KHR_maintenance1`/1.1+. The AMD extension for negative viewport height does not require a Y shift.
877    ///
878    /// This flag is `true` if the device has `VK_KHR_maintenance1`/1.1+ and `false` otherwise (i.e. in the case of `VK_AMD_negative_viewport_height`).
879    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") // TODO: Real Debug impl
888    }
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            // Keep variables outside the if-else block to ensure they do not
920            // go out of scope while we hold a pointer to them
921            let mut buffer: [u8; 64] = [0u8; 64];
922            let buffer_vec: Vec<u8>;
923
924            // Append a null terminator to the string
925            let name_cstr = if name.len() < 64 {
926                // Common case, string is very small. Allocate a copy on the stack.
927                std::ptr::copy_nonoverlapping(name.as_ptr(), buffer.as_mut_ptr(), name.len());
928                // Add null terminator
929                buffer[name.len()] = 0;
930                CStr::from_bytes_with_nul(&buffer[..name.len() + 1]).unwrap()
931            } else {
932                // Less common case, the string is large.
933                // This requires a heap allocation.
934                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
953// Need to explicitly synchronize on submission and present.
954pub 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        //TODO: avoid heap allocations
981        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 count is zero, AMD driver crashes if nullptr is not set for stage masks
998        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        //TODO: avoid heap allocations
1029        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        // Set buffer bindings
1062        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        // Set opaque image bindings
1091        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        // Set image bindings
1121        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        // TODO temporary hack as method is not yet exposed, https://github.com/MaikKlein/ash/issues/342
1137        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}