diff --git a/src/backend/vulkan/src/device.rs b/src/backend/vulkan/src/device.rs index 63c63cf2bb..329635d2ad 100644 --- a/src/backend/vulkan/src/device.rs +++ b/src/backend/vulkan/src/device.rs @@ -1216,37 +1216,12 @@ impl d::Device for super::Device { let is_cube = image .flags .intersects(vk::ImageCreateFlags::CUBE_COMPATIBLE); - let mut image_view_info; - let mut info = vk::ImageViewCreateInfo::builder() - .flags(vk::ImageViewCreateFlags::empty()) - .image(image.raw) - .view_type(match conv::map_view_kind(kind, image.ty, is_cube) { - Some(ty) => ty, - None => return Err(image::ViewCreationError::BadKind(kind)), - }) - .format(conv::map_format(format)) - .components(conv::map_swizzle(swizzle)) - .subresource_range(conv::map_subresource_range(&range)); - - if self.shared.image_view_usage { - image_view_info = vk::ImageViewUsageCreateInfo::builder() - .usage(conv::map_image_usage(usage)) - .build(); - info = info.push_next(&mut image_view_info); - } - - let result = self.shared.raw.create_image_view(&info, None); + let view_type = match conv::map_view_kind(kind, image.ty, is_cube) { + Some(ty) => ty, + None => return Err(image::ViewCreationError::BadKind(kind)), + }; - match result { - Ok(raw) => Ok(n::ImageView { - image: image.raw, - raw, - range, - }), - Err(vk::Result::ERROR_OUT_OF_HOST_MEMORY) => Err(d::OutOfMemory::Host.into()), - Err(vk::Result::ERROR_OUT_OF_DEVICE_MEMORY) => Err(d::OutOfMemory::Device.into()), - _ => unreachable!(), - } + self.image_view_from_raw(image.raw, view_type, format, swizzle, usage, range) } unsafe fn create_descriptor_pool( @@ -2030,6 +2005,45 @@ impl super::Device { Ok((swapchain, images)) } + + pub unsafe fn image_view_from_raw( + &self, + raw_image: vk::Image, + view_type: vk::ImageViewType, + format: format::Format, + swizzle: format::Swizzle, + usage: image::Usage, + range: image::SubresourceRange, + ) -> Result { + let mut image_view_info; + let mut info = vk::ImageViewCreateInfo::builder() + .flags(vk::ImageViewCreateFlags::empty()) + .image(raw_image) + .view_type(view_type) + .format(conv::map_format(format)) + .components(conv::map_swizzle(swizzle)) + .subresource_range(conv::map_subresource_range(&range)); + + if self.shared.image_view_usage { + image_view_info = vk::ImageViewUsageCreateInfo::builder() + .usage(conv::map_image_usage(usage)) + .build(); + info = info.push_next(&mut image_view_info); + } + + let result = self.shared.raw.create_image_view(&info, None); + + match result { + Ok(raw) => Ok(n::ImageView { + image: raw_image, + raw, + range, + }), + Err(vk::Result::ERROR_OUT_OF_HOST_MEMORY) => Err(d::OutOfMemory::Host.into()), + Err(vk::Result::ERROR_OUT_OF_DEVICE_MEMORY) => Err(d::OutOfMemory::Device.into()), + _ => unreachable!(), + } + } } #[test] diff --git a/src/backend/vulkan/src/lib.rs b/src/backend/vulkan/src/lib.rs index 36ec2a5fe5..d5f93f6ca1 100644 --- a/src/backend/vulkan/src/lib.rs +++ b/src/backend/vulkan/src/lib.rs @@ -28,6 +28,8 @@ extern crate objc; #[cfg(not(feature = "use-rtld-next"))] use ash::Entry; +#[cfg(feature = "use-rtld-next")] +type Entry = ash::EntryCustom<()>; use ash::{ extensions::{ext, khr, nv::MeshShader}, version::{DeviceV1_0, EntryV1_0, InstanceV1_0}, @@ -53,9 +55,6 @@ use std::{ thread, unreachable, }; -#[cfg(feature = "use-rtld-next")] -use ash::EntryCustom; - mod command; mod conv; mod device; @@ -72,6 +71,7 @@ const ROUGH_MAX_ATTACHMENT_COUNT: usize = 5; pub struct RawInstance { inner: ash::Instance, + handle_is_external: bool, debug_messenger: Option, get_physical_device_properties: Option, } @@ -95,7 +95,10 @@ impl Drop for RawInstance { } None => {} } - self.inner.destroy_instance(None); + + if !self.handle_is_external { + self.inner.destroy_instance(None); + } } } } @@ -151,11 +154,7 @@ pub struct Instance { /// Supported extensions of this instance. pub extensions: Vec<&'static CStr>, - #[cfg(not(feature = "use-rtld-next"))] pub entry: Entry, - - #[cfg(feature = "use-rtld-next")] - pub entry: EntryCustom<()>, } impl fmt::Debug for Instance { @@ -341,6 +340,200 @@ unsafe extern "system" fn debug_report_callback( vk::FALSE } +impl Instance { + pub fn required_extensions( + entry: &Entry, + driver_api_version: Version, + ) -> Result, hal::UnsupportedBackend> { + let instance_extensions = entry + .enumerate_instance_extension_properties() + .map_err(|e| { + info!("Unable to enumerate instance extensions: {:?}", e); + hal::UnsupportedBackend + })?; + + // Check our extensions against the available extensions + let mut extensions: Vec<&'static CStr> = Vec::new(); + extensions.push(khr::Surface::name()); + + // Platform-specific WSI extensions + if cfg!(all( + unix, + not(target_os = "android"), + not(target_os = "macos") + )) { + extensions.push(khr::XlibSurface::name()); + extensions.push(khr::XcbSurface::name()); + extensions.push(khr::WaylandSurface::name()); + } + if cfg!(target_os = "android") { + extensions.push(khr::AndroidSurface::name()); + } + if cfg!(target_os = "windows") { + extensions.push(khr::Win32Surface::name()); + } + if cfg!(target_os = "macos") { + extensions.push(ash::extensions::mvk::MacOSSurface::name()); + } + + extensions.push(ext::DebugUtils::name()); + if cfg!(debug_assertions) { + #[allow(deprecated)] + extensions.push(ext::DebugReport::name()); + } + + extensions.push(vk::KhrGetPhysicalDeviceProperties2Fn::name()); + + // VK_KHR_storage_buffer_storage_class required for `Naga` on Vulkan 1.0 devices + if driver_api_version == Version::V1_0 { + extensions.push(vk::KhrStorageBufferStorageClassFn::name()); + } + + // Only keep available extensions. + extensions.retain(|&ext| { + if instance_extensions + .iter() + .find(|inst_ext| unsafe { CStr::from_ptr(inst_ext.extension_name.as_ptr()) == ext }) + .is_some() + { + true + } else { + info!("Unable to find extension: {}", ext.to_string_lossy()); + false + } + }); + Ok(extensions) + } + + pub fn required_layers(entry: &Entry) -> Result, hal::UnsupportedBackend> { + let instance_layers = entry.enumerate_instance_layer_properties().map_err(|e| { + info!("Unable to enumerate instance layers: {:?}", e); + hal::UnsupportedBackend + })?; + + // Check requested layers against the available layers + let mut layers: Vec<&'static CStr> = Vec::new(); + if cfg!(debug_assertions) { + layers.push(CStr::from_bytes_with_nul(b"VK_LAYER_KHRONOS_validation\0").unwrap()); + } + + // Only keep available layers. + layers.retain(|&layer| { + if instance_layers + .iter() + .find(|inst_layer| unsafe { + CStr::from_ptr(inst_layer.layer_name.as_ptr()) == layer + }) + .is_some() + { + true + } else { + warn!("Unable to find layer: {}", layer.to_string_lossy()); + false + } + }); + Ok(layers) + } + + /// # Safety + /// `raw_instance` must be created using at least the extensions provided by `Instance::required_extensions()` + /// and the layers provided by `Instance::required_extensions()`. + /// `driver_api_version` must match the version used to create `raw_instance`. + /// `extensions` must match the extensions used to create `raw_instance`. + /// `raw_instance` must be manually destroyed *after* gfx-hal Instance has been dropped. + pub unsafe fn from_raw( + entry: Entry, + raw_instance: ash::Instance, + driver_api_version: Version, + extensions: Vec<&'static CStr>, + ) -> Result { + Instance::inner_create(entry, raw_instance, true, driver_api_version, extensions) + } + + fn inner_create( + entry: Entry, + instance: ash::Instance, + handle_is_external: bool, + driver_api_version: Version, + extensions: Vec<&'static CStr>, + ) -> Result { + if driver_api_version == Version::V1_0 + && !extensions.contains(&vk::KhrStorageBufferStorageClassFn::name()) + { + warn!("Unable to create Vulkan instance. Required VK_KHR_storage_buffer_storage_class extension is not supported"); + return Err(hal::UnsupportedBackend); + } + + let instance_extensions = entry + .enumerate_instance_extension_properties() + .map_err(|e| { + info!("Unable to enumerate instance extensions: {:?}", e); + hal::UnsupportedBackend + })?; + + let get_physical_device_properties = extensions + .iter() + .find(|&&ext| ext == vk::KhrGetPhysicalDeviceProperties2Fn::name()) + .map(|_| { + vk::KhrGetPhysicalDeviceProperties2Fn::load(|name| unsafe { + std::mem::transmute( + entry.get_instance_proc_addr(instance.handle(), name.as_ptr()), + ) + }) + }); + + #[allow(deprecated)] // `DebugReport` + let debug_messenger = { + // make sure VK_EXT_debug_utils is available + if instance_extensions.iter().any(|props| unsafe { + CStr::from_ptr(props.extension_name.as_ptr()) == ext::DebugUtils::name() + }) { + let ext = ext::DebugUtils::new(&entry, &instance); + let info = vk::DebugUtilsMessengerCreateInfoEXT::builder() + .flags(vk::DebugUtilsMessengerCreateFlagsEXT::empty()) + .message_severity(vk::DebugUtilsMessageSeverityFlagsEXT::all()) + .message_type(vk::DebugUtilsMessageTypeFlagsEXT::all()) + .pfn_user_callback(Some(debug_utils_messenger_callback)); + let handle = unsafe { ext.create_debug_utils_messenger(&info, None) }.unwrap(); + Some(DebugMessenger::Utils(ext, handle)) + } else if cfg!(debug_assertions) + && instance_extensions.iter().any(|props| unsafe { + CStr::from_ptr(props.extension_name.as_ptr()) == ext::DebugReport::name() + }) + { + let ext = ext::DebugReport::new(&entry, &instance); + let info = vk::DebugReportCallbackCreateInfoEXT::builder() + .flags(vk::DebugReportFlagsEXT::all()) + .pfn_callback(Some(debug_report_callback)); + let handle = unsafe { ext.create_debug_report_callback(&info, None) }.unwrap(); + Some(DebugMessenger::Report(ext, handle)) + } else { + None + } + }; + + Ok(Instance { + raw: Arc::new(RawInstance { + inner: instance, + handle_is_external, + debug_messenger, + get_physical_device_properties, + }), + extensions, + entry, + }) + } + + /// # Safety + /// `raw_physical_device` must be created from `self` (or from the inner raw handle) + pub unsafe fn adapter_from_raw( + &self, + raw_physical_device: vk::PhysicalDevice, + ) -> adapter::Adapter { + physical_device::load_adapter(&self.raw, raw_physical_device) + } +} + impl hal::Instance for Instance { fn create(name: &str, version: u32) -> Result { #[cfg(not(feature = "use-rtld-next"))] @@ -353,7 +546,7 @@ impl hal::Instance for Instance { }; #[cfg(feature = "use-rtld-next")] - let entry = EntryCustom::new_custom((), |_, name| unsafe { + let entry = Entry::new_custom((), |_, name| unsafe { libc::dlsym(libc::RTLD_NEXT, name.as_ptr()) }); @@ -397,105 +590,9 @@ impl hal::Instance for Instance { .into() }); - let instance_extensions = entry - .enumerate_instance_extension_properties() - .map_err(|e| { - info!("Unable to enumerate instance extensions: {:?}", e); - hal::UnsupportedBackend - })?; - - let instance_layers = entry.enumerate_instance_layer_properties().map_err(|e| { - info!("Unable to enumerate instance layers: {:?}", e); - hal::UnsupportedBackend - })?; - - // Check our extensions against the available extensions - let extensions = { - let mut extensions: Vec<&'static CStr> = Vec::new(); - extensions.push(khr::Surface::name()); - - // Platform-specific WSI extensions - if cfg!(all( - unix, - not(target_os = "android"), - not(target_os = "macos") - )) { - extensions.push(khr::XlibSurface::name()); - extensions.push(khr::XcbSurface::name()); - extensions.push(khr::WaylandSurface::name()); - } - if cfg!(target_os = "android") { - extensions.push(khr::AndroidSurface::name()); - } - if cfg!(target_os = "windows") { - extensions.push(khr::Win32Surface::name()); - } - if cfg!(target_os = "macos") { - extensions.push(ash::extensions::mvk::MacOSSurface::name()); - } - - extensions.push(ext::DebugUtils::name()); - if cfg!(debug_assertions) { - #[allow(deprecated)] - extensions.push(ext::DebugReport::name()); - } - - extensions.push(vk::KhrGetPhysicalDeviceProperties2Fn::name()); - - // VK_KHR_storage_buffer_storage_class required for `Naga` on Vulkan 1.0 devices - if driver_api_version == Version::V1_0 { - extensions.push(vk::KhrStorageBufferStorageClassFn::name()); - } - - // Only keep available extensions. - extensions.retain(|&ext| { - if instance_extensions - .iter() - .find(|inst_ext| unsafe { - CStr::from_ptr(inst_ext.extension_name.as_ptr()) == ext - }) - .is_some() - { - true - } else { - info!("Unable to find extension: {}", ext.to_string_lossy()); - false - } - }); - extensions - }; - - if driver_api_version == Version::V1_0 - && !extensions.contains(&vk::KhrStorageBufferStorageClassFn::name()) - { - warn!("Unable to create Vulkan instance. Required VK_KHR_storage_buffer_storage_class extension is not supported"); - return Err(hal::UnsupportedBackend); - } + let extensions = Instance::required_extensions(&entry, driver_api_version)?; - // Check requested layers against the available layers - let layers = { - let mut layers: Vec<&'static CStr> = Vec::new(); - if cfg!(debug_assertions) { - layers.push(CStr::from_bytes_with_nul(b"VK_LAYER_KHRONOS_validation\0").unwrap()); - } - - // Only keep available layers. - layers.retain(|&layer| { - if instance_layers - .iter() - .find(|inst_layer| unsafe { - CStr::from_ptr(inst_layer.layer_name.as_ptr()) == layer - }) - .is_some() - { - true - } else { - warn!("Unable to find layer: {}", layer.to_string_lossy()); - false - } - }); - layers - }; + let layers = Instance::required_layers(&entry)?; let instance = { let str_pointers = layers @@ -519,56 +616,7 @@ impl hal::Instance for Instance { })? }; - let get_physical_device_properties = extensions - .iter() - .find(|&&ext| ext == vk::KhrGetPhysicalDeviceProperties2Fn::name()) - .map(|_| { - vk::KhrGetPhysicalDeviceProperties2Fn::load(|name| unsafe { - std::mem::transmute( - entry.get_instance_proc_addr(instance.handle(), name.as_ptr()), - ) - }) - }); - - #[allow(deprecated)] // `DebugReport` - let debug_messenger = { - // make sure VK_EXT_debug_utils is available - if instance_extensions.iter().any(|props| unsafe { - CStr::from_ptr(props.extension_name.as_ptr()) == ext::DebugUtils::name() - }) { - let ext = ext::DebugUtils::new(&entry, &instance); - let info = vk::DebugUtilsMessengerCreateInfoEXT::builder() - .flags(vk::DebugUtilsMessengerCreateFlagsEXT::empty()) - .message_severity(vk::DebugUtilsMessageSeverityFlagsEXT::all()) - .message_type(vk::DebugUtilsMessageTypeFlagsEXT::all()) - .pfn_user_callback(Some(debug_utils_messenger_callback)); - let handle = unsafe { ext.create_debug_utils_messenger(&info, None) }.unwrap(); - Some(DebugMessenger::Utils(ext, handle)) - } else if cfg!(debug_assertions) - && instance_extensions.iter().any(|props| unsafe { - CStr::from_ptr(props.extension_name.as_ptr()) == ext::DebugReport::name() - }) - { - let ext = ext::DebugReport::new(&entry, &instance); - let info = vk::DebugReportCallbackCreateInfoEXT::builder() - .flags(vk::DebugReportFlagsEXT::all()) - .pfn_callback(Some(debug_report_callback)); - let handle = unsafe { ext.create_debug_report_callback(&info, None) }.unwrap(); - Some(DebugMessenger::Report(ext, handle)) - } else { - None - } - }; - - Ok(Instance { - raw: Arc::new(RawInstance { - inner: instance, - debug_messenger, - get_physical_device_properties, - }), - extensions, - entry, - }) + Instance::inner_create(entry, instance, false, driver_api_version, extensions) } fn enumerate_adapters(&self) -> Vec> { @@ -700,6 +748,7 @@ impl ExtensionFn { #[doc(hidden)] pub struct RawDevice { raw: ash::Device, + handle_is_external: bool, features: Features, instance: Arc, extension_fns: DeviceExtensionFunctions, @@ -719,8 +768,10 @@ impl fmt::Debug for RawDevice { } impl Drop for RawDevice { fn drop(&mut self) { - unsafe { - self.raw.destroy_device(None); + if !self.handle_is_external { + unsafe { + self.raw.destroy_device(None); + } } } } diff --git a/src/backend/vulkan/src/physical_device.rs b/src/backend/vulkan/src/physical_device.rs index 85acd4617f..c7704856e0 100644 --- a/src/backend/vulkan/src/physical_device.rs +++ b/src/backend/vulkan/src/physical_device.rs @@ -678,6 +678,189 @@ pub struct PhysicalDevice { available_features: Features, } +impl PhysicalDevice { + /// # Safety + /// `raw_device` must be created from `self` (or from the inner raw handle) + /// `raw_device` must be created with `requested_features` + pub unsafe fn gpu_from_raw( + &self, + raw_device: ash::Device, + families: &[(&QueueFamily, &[queue::QueuePriority])], + requested_features: Features, + ) -> Result, CreationError> { + let enabled_extensions = self.enabled_extensions(requested_features)?; + Ok(self.inner_create_gpu( + raw_device, + true, + families, + requested_features, + enabled_extensions, + )) + } + + unsafe fn inner_create_gpu( + &self, + device_raw: ash::Device, + handle_is_external: bool, + families: &[(&QueueFamily, &[queue::QueuePriority])], + requested_features: Features, + enabled_extensions: Vec<&CStr>, + ) -> adapter::Gpu { + let valid_ash_memory_types = { + let mem_properties = self + .instance + .inner + .get_physical_device_memory_properties(self.handle); + mem_properties.memory_types[..mem_properties.memory_type_count as usize] + .iter() + .enumerate() + .fold(0, |u, (i, mem)| { + if self.known_memory_flags.contains(mem.property_flags) { + u | (1 << i) + } else { + u + } + }) + }; + + let supports_vulkan12_imageless_framebuffer = self + .device_features + .vulkan_1_2 + .map_or(false, |features| features.imageless_framebuffer == vk::TRUE); + + let swapchain_fn = Swapchain::new(&self.instance.inner, &device_raw); + + let mesh_fn = if enabled_extensions.contains(&MeshShader::name()) { + Some(ExtensionFn::Extension(MeshShader::new( + &self.instance.inner, + &device_raw, + ))) + } else { + None + }; + + let indirect_count_fn = if enabled_extensions.contains(&DrawIndirectCount::name()) { + Some(ExtensionFn::Extension(DrawIndirectCount::new( + &self.instance.inner, + &device_raw, + ))) + } else if self.device_info.api_version() >= Version::V1_2 { + Some(ExtensionFn::Promoted) + } else { + None + }; + + #[cfg(feature = "naga")] + let naga_options = { + use naga::back::spv; + let capabilities = [ + spv::Capability::Shader, + spv::Capability::Matrix, + spv::Capability::InputAttachment, + spv::Capability::Sampled1D, + spv::Capability::Image1D, + spv::Capability::SampledBuffer, + spv::Capability::ImageBuffer, + spv::Capability::ImageQuery, + spv::Capability::DerivativeControl, + //TODO: fill out the rest + ]; + let mut flags = spv::WriterFlags::empty(); + flags.set(spv::WriterFlags::DEBUG, cfg!(debug_assertions)); + flags.set( + spv::WriterFlags::ADJUST_COORDINATE_SPACE, + !requested_features.contains(hal::Features::NDC_Y_UP), + ); + spv::Options { + lang_version: (1, 0), + flags, + capabilities: Some(capabilities.iter().cloned().collect()), + } + }; + + let device = Device { + shared: Arc::new(RawDevice { + raw: device_raw, + handle_is_external, + features: requested_features, + instance: Arc::clone(&self.instance), + extension_fns: DeviceExtensionFunctions { + mesh_shaders: mesh_fn, + draw_indirect_count: indirect_count_fn, + }, + flip_y_requires_shift: self.device_info.api_version() >= Version::V1_1 + || self + .device_info + .supports_extension(vk::KhrMaintenance1Fn::name()), + imageless_framebuffers: supports_vulkan12_imageless_framebuffer + || self + .device_info + .supports_extension(vk::KhrImagelessFramebufferFn::name()), + image_view_usage: self.device_info.api_version() >= Version::V1_1 + || self + .device_info + .supports_extension(vk::KhrMaintenance2Fn::name()), + timestamp_period: self.device_info.properties.limits.timestamp_period, + }), + vendor_id: self.device_info.properties.vendor_id, + valid_ash_memory_types, + render_doc: Default::default(), + #[cfg(feature = "naga")] + naga_options, + }; + + let device_arc = Arc::clone(&device.shared); + let queue_groups = families + .iter() + .map(|&(family, ref priorities)| { + let mut family_raw = + queue::QueueGroup::new(queue::QueueFamilyId(family.index as usize)); + for id in 0..priorities.len() { + let queue_raw = device_arc.raw.get_device_queue(family.index, id as _); + family_raw.add_queue(Queue { + raw: Arc::new(queue_raw), + device: device_arc.clone(), + swapchain_fn: swapchain_fn.clone(), + }); + } + family_raw + }) + .collect(); + + adapter::Gpu { + device, + queue_groups, + } + } + + fn enabled_extensions( + &self, + requested_features: Features, + ) -> Result, CreationError> { + use adapter::PhysicalDevice; + + if !self.features().contains(requested_features) { + return Err(CreationError::MissingFeature); + } + + let (supported_extensions, unsupported_extensions) = self + .device_info + .get_required_extensions(requested_features) + .iter() + .partition::, _>(|&&extension| { + self.device_info.supports_extension(extension) + }); + + if !unsupported_extensions.is_empty() { + warn!("Missing extensions: {:?}", unsupported_extensions); + } + + debug!("Supported extensions: {:?}", supported_extensions); + + Ok(supported_extensions) + } +} + pub(crate) fn load_adapter( instance: &Arc, device: vk::PhysicalDevice, @@ -777,44 +960,7 @@ impl adapter::PhysicalDevice for PhysicalDevice { }) .collect::>(); - if !self.features().contains(requested_features) { - return Err(CreationError::MissingFeature); - } - - let enabled_extensions = { - let (supported_extensions, unsupported_extensions) = self - .device_info - .get_required_extensions(requested_features) - .iter() - .partition::, _>(|&&extension| { - self.device_info.supports_extension(extension) - }); - - if !unsupported_extensions.is_empty() { - warn!("Missing extensions: {:?}", unsupported_extensions); - } - - debug!("Supported extensions: {:?}", supported_extensions); - - supported_extensions - }; - - let valid_ash_memory_types = { - let mem_properties = self - .instance - .inner - .get_physical_device_memory_properties(self.handle); - mem_properties.memory_types[..mem_properties.memory_type_count as usize] - .iter() - .enumerate() - .fold(0, |u, (i, mem)| { - if self.known_memory_flags.contains(mem.property_flags) { - u | (1 << i) - } else { - u - } - }) - }; + let enabled_extensions = self.enabled_extensions(requested_features)?; let supports_vulkan12_imageless_framebuffer = self .device_features @@ -867,108 +1013,13 @@ impl adapter::PhysicalDevice for PhysicalDevice { } }; - let swapchain_fn = Swapchain::new(&self.instance.inner, &device_raw); - - let mesh_fn = if enabled_extensions.contains(&MeshShader::name()) { - Some(ExtensionFn::Extension(MeshShader::new( - &self.instance.inner, - &device_raw, - ))) - } else { - None - }; - - let indirect_count_fn = if enabled_extensions.contains(&DrawIndirectCount::name()) { - Some(ExtensionFn::Extension(DrawIndirectCount::new( - &self.instance.inner, - &device_raw, - ))) - } else if self.device_info.api_version() >= Version::V1_2 { - Some(ExtensionFn::Promoted) - } else { - None - }; - - #[cfg(feature = "naga")] - let naga_options = { - use naga::back::spv; - let capabilities = [ - spv::Capability::Shader, - spv::Capability::Matrix, - spv::Capability::InputAttachment, - spv::Capability::Sampled1D, - spv::Capability::Image1D, - spv::Capability::SampledBuffer, - spv::Capability::ImageBuffer, - spv::Capability::ImageQuery, - spv::Capability::DerivativeControl, - //TODO: fill out the rest - ]; - let mut flags = spv::WriterFlags::empty(); - flags.set(spv::WriterFlags::DEBUG, cfg!(debug_assertions)); - flags.set( - spv::WriterFlags::ADJUST_COORDINATE_SPACE, - !requested_features.contains(hal::Features::NDC_Y_UP), - ); - spv::Options { - lang_version: (1, 0), - flags, - capabilities: Some(capabilities.iter().cloned().collect()), - } - }; - - let device = Device { - shared: Arc::new(RawDevice { - raw: device_raw, - features: requested_features, - instance: Arc::clone(&self.instance), - extension_fns: DeviceExtensionFunctions { - mesh_shaders: mesh_fn, - draw_indirect_count: indirect_count_fn, - }, - flip_y_requires_shift: self.device_info.api_version() >= Version::V1_1 - || self - .device_info - .supports_extension(vk::KhrMaintenance1Fn::name()), - imageless_framebuffers: supports_vulkan12_imageless_framebuffer - || self - .device_info - .supports_extension(vk::KhrImagelessFramebufferFn::name()), - image_view_usage: self.device_info.api_version() >= Version::V1_1 - || self - .device_info - .supports_extension(vk::KhrMaintenance2Fn::name()), - timestamp_period: self.device_info.properties.limits.timestamp_period, - }), - vendor_id: self.device_info.properties.vendor_id, - valid_ash_memory_types, - render_doc: Default::default(), - #[cfg(feature = "naga")] - naga_options, - }; - - let device_arc = Arc::clone(&device.shared); - let queue_groups = families - .iter() - .map(|&(family, ref priorities)| { - let mut family_raw = - queue::QueueGroup::new(queue::QueueFamilyId(family.index as usize)); - for id in 0..priorities.len() { - let queue_raw = device_arc.raw.get_device_queue(family.index, id as _); - family_raw.add_queue(Queue { - raw: Arc::new(queue_raw), - device: device_arc.clone(), - swapchain_fn: swapchain_fn.clone(), - }); - } - family_raw - }) - .collect(); - - Ok(adapter::Gpu { - device, - queue_groups, - }) + Ok(self.inner_create_gpu( + device_raw, + false, + families, + requested_features, + enabled_extensions, + )) } fn format_properties(&self, format: Option) -> format::Properties {