From d30bc2cc455d17c50416ef7b1b198d536af705a3 Mon Sep 17 00:00:00 2001 From: Jinlei Li Date: Sun, 22 Jan 2023 17:14:30 +0800 Subject: [PATCH] Handle vulkan backend --- wgpu-core/src/device/mod.rs | 24 ++++++++++++++++++------ wgpu-hal/examples/halmark/main.rs | 1 + wgpu-hal/src/lib.rs | 3 +++ wgpu-hal/src/vulkan/adapter.rs | 3 +++ wgpu-hal/src/vulkan/device.rs | 27 +++++++++++++++++++++++++-- 5 files changed, 50 insertions(+), 8 deletions(-) diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index d16e5ee54ff..4b93a4010a0 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -5261,12 +5261,6 @@ impl Global { Err(_) => break E::InvalidSurface, }; - for format in config.view_formats.iter() { - if config.format.remove_srgb_suffix() != format.remove_srgb_suffix() { - break 'outter E::InvalidViewFormat(*format, config.format); - } - } - let caps = unsafe { let suf = A::get_surface(surface); let adapter = &adapter_guard[device.adapter_id.value]; @@ -5276,6 +5270,23 @@ impl Global { } }; + let mut hal_view_formats = vec![config.format]; + for format in config.view_formats.iter() { + if *format == config.format { + continue; + } + if !caps.formats.contains(&config.format) { + break 'outter E::UnsupportedFormat { + requested: config.format, + available: caps.formats.clone(), + }; + } + if config.format.remove_srgb_suffix() != format.remove_srgb_suffix() { + break 'outter E::InvalidViewFormat(*format, config.format); + } + hal_view_formats.push(*format); + } + let num_frames = present::DESIRED_NUM_FRAMES .clamp(*caps.swap_chain_sizes.start(), *caps.swap_chain_sizes.end()); let mut hal_config = hal::SurfaceConfiguration { @@ -5289,6 +5300,7 @@ impl Global { depth_or_array_layers: 1, }, usage: conv::map_texture_usage(config.usage, hal::FormatAspects::COLOR), + view_formats: hal_view_formats, }; if let Err(error) = validate_surface_configuration(&mut hal_config, &caps) { diff --git a/wgpu-hal/examples/halmark/main.rs b/wgpu-hal/examples/halmark/main.rs index 6bcde926c8c..7b52e407210 100644 --- a/wgpu-hal/examples/halmark/main.rs +++ b/wgpu-hal/examples/halmark/main.rs @@ -139,6 +139,7 @@ impl Example { depth_or_array_layers: 1, }, usage: hal::TextureUses::COLOR_TARGET, + view_formats: vec![], }; unsafe { surface.configure(&device, &surface_config).unwrap(); diff --git a/wgpu-hal/src/lib.rs b/wgpu-hal/src/lib.rs index 57a1854b741..2a042040346 100644 --- a/wgpu-hal/src/lib.rs +++ b/wgpu-hal/src/lib.rs @@ -1093,6 +1093,9 @@ pub struct SurfaceConfiguration { pub extent: wgt::Extent3d, /// Allowed usage of surface textures, pub usage: TextureUses, + /// Allows views of swapchain texture to have a different format + /// than the texture does. + pub view_formats: Vec, } #[derive(Debug, Clone)] diff --git a/wgpu-hal/src/vulkan/adapter.rs b/wgpu-hal/src/vulkan/adapter.rs index 12a700d4739..2709a35cc62 100644 --- a/wgpu-hal/src/vulkan/adapter.rs +++ b/wgpu-hal/src/vulkan/adapter.rs @@ -564,6 +564,9 @@ impl PhysicalDeviceCapabilities { // Require `VK_KHR_swapchain` extensions.push(vk::KhrSwapchainFn::name()); + // `KhrSwapchainMutableFormatFn` extension is requires support for Vulkan 1.0: + // https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_KHR_swapchain_mutable_format.html + extensions.push(vk::KhrSwapchainMutableFormatFn::name()); if self.effective_api_version < vk::API_VERSION_1_1 { // Require either `VK_KHR_maintenance1` or `VK_AMD_negative_viewport_height` diff --git a/wgpu-hal/src/vulkan/device.rs b/wgpu-hal/src/vulkan/device.rs index 62843487c8a..e139b14ed70 100644 --- a/wgpu-hal/src/vulkan/device.rs +++ b/wgpu-hal/src/vulkan/device.rs @@ -546,8 +546,25 @@ impl super::Device { } else { vk::ColorSpaceKHR::SRGB_NONLINEAR }; - let info = vk::SwapchainCreateInfoKHR::builder() - .flags(vk::SwapchainCreateFlagsKHR::empty()) + + let mut raw_flags = vk::SwapchainCreateFlagsKHR::empty(); + let mut raw_view_formats: Vec = vec![]; + if config.view_formats.len() > 1 + && (self.shared_instance().driver_api_version >= vk::API_VERSION_1_2 + || self + .enabled_device_extensions() + .contains(&vk::KhrImageFormatListFn::name())) + { + raw_flags |= vk::SwapchainCreateFlagsKHR::MUTABLE_FORMAT; + raw_view_formats = config + .view_formats + .iter() + .map(|f| self.shared.private_caps.map_texture_format(*f)) + .collect(); + } + + let mut info = vk::SwapchainCreateInfoKHR::builder() + .flags(raw_flags) .surface(surface.raw) .min_image_count(config.swap_chain_size) .image_format(self.shared.private_caps.map_texture_format(config.format)) @@ -565,6 +582,12 @@ impl super::Device { .clipped(true) .old_swapchain(old_swapchain); + let mut format_list_info = vk::ImageFormatListCreateInfo::builder(); + if !raw_view_formats.is_empty() { + format_list_info = format_list_info.view_formats(&raw_view_formats); + info = info.push_next(&mut format_list_info); + } + let result = { profiling::scope!("vkCreateSwapchainKHR"); unsafe { functor.create_swapchain(&info, None) }