From b39a990f2f41fdeb45d4c7178eea4be8acc5d1b5 Mon Sep 17 00:00:00 2001 From: Jinlei Li Date: Sat, 28 Jan 2023 22:44:56 +0800 Subject: [PATCH 1/2] vk: fix surface view formats validation error --- wgpu-hal/src/vulkan/device.rs | 62 ++++++++++++++++++++++++++++----- wgpu-hal/src/vulkan/instance.rs | 13 ++++++- wgpu-hal/src/vulkan/mod.rs | 4 +++ 3 files changed, 69 insertions(+), 10 deletions(-) diff --git a/wgpu-hal/src/vulkan/device.rs b/wgpu-hal/src/vulkan/device.rs index e7c3856e7e4..27d5be74598 100644 --- a/wgpu-hal/src/vulkan/device.rs +++ b/wgpu-hal/src/vulkan/device.rs @@ -217,20 +217,32 @@ impl super::DeviceShared { .iter() .map(|at| self.private_caps.map_texture_format(at.view_format)) .collect::>(); + let vk_view_formats_list = e + .key() + .attachments + .iter() + .map(|at| at.raw_view_formats.clone()) + .collect::>(); + let vk_image_infos = e .key() .attachments .iter() .enumerate() .map(|(i, at)| { - vk::FramebufferAttachmentImageInfo::builder() + let mut info = vk::FramebufferAttachmentImageInfo::builder() .usage(conv::map_texture_usage(at.view_usage)) .flags(at.raw_image_flags) .width(e.key().extent.width) .height(e.key().extent.height) - .layer_count(e.key().extent.depth_or_array_layers) - .view_formats(&vk_view_formats[i..i + 1]) - .build() + .layer_count(e.key().extent.depth_or_array_layers); + // https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkRenderPassBeginInfo.html#VUID-VkRenderPassBeginInfo-framebuffer-03214 + if vk_view_formats_list[i].is_empty() { + info = info.view_formats(&vk_view_formats[i..i + 1]); + } else { + info = info.view_formats(&vk_view_formats_list[i]); + }; + info.build() }) .collect::>(); @@ -550,6 +562,7 @@ impl super::Device { let original_format = self.shared.private_caps.map_texture_format(config.format); let mut raw_flags = vk::SwapchainCreateFlagsKHR::empty(); let mut raw_view_formats: Vec = vec![]; + let mut wgt_view_formats = vec![]; if !config.view_formats.is_empty() { raw_flags |= vk::SwapchainCreateFlagsKHR::MUTABLE_FORMAT; raw_view_formats = config @@ -558,6 +571,9 @@ impl super::Device { .map(|f| self.shared.private_caps.map_texture_format(*f)) .collect(); raw_view_formats.push(original_format); + + wgt_view_formats = config.view_formats.clone(); + wgt_view_formats.push(config.format); } let mut info = vk::SwapchainCreateInfoKHR::builder() @@ -617,11 +633,13 @@ impl super::Device { Ok(super::Swapchain { raw, + raw_flags, functor, device: Arc::clone(&self.shared), fence, images, config: config.clone(), + view_formats: wgt_view_formats, }) } @@ -630,11 +648,26 @@ impl super::Device { /// - `vk_image` must be created respecting `desc` /// - If `drop_guard` is `Some`, the application must manually destroy the image handle. This /// can be done inside the `Drop` impl of `drop_guard`. + /// - If the `ImageCreateFlags` does not contain `MUTABLE_FORMAT`, the `view_formats` of `desc` must be empty. pub unsafe fn texture_from_raw( vk_image: vk::Image, desc: &crate::TextureDescriptor, drop_guard: Option, ) -> super::Texture { + let mut raw_flags = vk::ImageCreateFlags::empty(); + let mut view_formats = vec![]; + for tf in desc.view_formats.iter() { + if *tf == desc.format { + continue; + } + view_formats.push(*tf); + } + if !view_formats.is_empty() { + raw_flags |= + vk::ImageCreateFlags::MUTABLE_FORMAT | vk::ImageCreateFlags::EXTENDED_USAGE; + view_formats.push(desc.format) + } + super::Texture { raw: vk_image, drop_guard, @@ -644,6 +677,7 @@ impl super::Device { format_info: desc.format.describe(), raw_flags: vk::ImageCreateFlags::empty(), copy_size: crate::CopyExtent::map_extent_to_copy_size(&desc.size, desc.dimension), + view_formats, } } @@ -916,20 +950,24 @@ impl crate::Device for super::Device { } let original_format = self.shared.private_caps.map_texture_format(desc.format); - let mut hal_view_formats: Vec = vec![]; + let mut vk_view_formats = vec![]; + let mut wgt_view_formats = vec![]; if !desc.view_formats.is_empty() { raw_flags |= vk::ImageCreateFlags::MUTABLE_FORMAT; + wgt_view_formats = desc.view_formats.clone(); + wgt_view_formats.push(desc.format); + if self.shared_instance().driver_api_version >= vk::API_VERSION_1_2 || self .enabled_device_extensions() .contains(&vk::KhrImageFormatListFn::name()) { - hal_view_formats = desc + vk_view_formats = desc .view_formats .iter() .map(|f| self.shared.private_caps.map_texture_format(*f)) .collect(); - hal_view_formats.push(original_format) + vk_view_formats.push(original_format) } } @@ -951,8 +989,8 @@ impl crate::Device for super::Device { .initial_layout(vk::ImageLayout::UNDEFINED); let mut format_list_info = vk::ImageFormatListCreateInfo::builder(); - if !hal_view_formats.is_empty() { - format_list_info = format_list_info.view_formats(&hal_view_formats); + if !vk_view_formats.is_empty() { + format_list_info = format_list_info.view_formats(&vk_view_formats); vk_info = vk_info.push_next(&mut format_list_info); } @@ -993,6 +1031,7 @@ impl crate::Device for super::Device { format_info: desc.format.describe(), raw_flags, copy_size, + view_formats: wgt_view_formats, }) } unsafe fn destroy_texture(&self, texture: super::Texture) { @@ -1048,6 +1087,11 @@ impl crate::Device for super::Device { raw_image_flags: texture.raw_flags, view_usage, view_format: desc.format, + raw_view_formats: texture + .view_formats + .iter() + .map(|tf| self.shared.private_caps.map_texture_format(*tf)) + .collect(), }; Ok(super::TextureView { diff --git a/wgpu-hal/src/vulkan/instance.rs b/wgpu-hal/src/vulkan/instance.rs index bb0e3330982..16500b00f55 100644 --- a/wgpu-hal/src/vulkan/instance.rs +++ b/wgpu-hal/src/vulkan/instance.rs @@ -784,6 +784,16 @@ impl crate::Surface for super::Surface { .map_err(crate::DeviceError::from)?; unsafe { sc.device.raw.reset_fences(fences) }.map_err(crate::DeviceError::from)?; + // https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkRenderPassBeginInfo.html#VUID-VkRenderPassBeginInfo-framebuffer-03209 + let raw_flags = if sc + .raw_flags + .contains(vk::SwapchainCreateFlagsKHR::MUTABLE_FORMAT) + { + vk::ImageCreateFlags::MUTABLE_FORMAT | vk::ImageCreateFlags::EXTENDED_USAGE + } else { + vk::ImageCreateFlags::empty() + }; + let texture = super::SurfaceTexture { index, texture: super::Texture { @@ -793,11 +803,12 @@ impl crate::Surface for super::Surface { usage: sc.config.usage, aspects: crate::FormatAspects::COLOR, format_info: sc.config.format.describe(), - raw_flags: vk::ImageCreateFlags::empty(), + raw_flags, copy_size: conv::map_extent_to_copy_size( &sc.config.extent, wgt::TextureDimension::D2, ), + view_formats: sc.view_formats.clone(), }, }; Ok(Some(crate::AcquiredSurfaceTexture { diff --git a/wgpu-hal/src/vulkan/mod.rs b/wgpu-hal/src/vulkan/mod.rs index 3c2ebbb5e97..fff9655490a 100644 --- a/wgpu-hal/src/vulkan/mod.rs +++ b/wgpu-hal/src/vulkan/mod.rs @@ -96,11 +96,13 @@ pub struct Instance { struct Swapchain { raw: vk::SwapchainKHR, + raw_flags: vk::SwapchainCreateFlagsKHR, functor: khr::Swapchain, device: Arc, fence: vk::Fence, images: Vec, config: crate::SurfaceConfiguration, + view_formats: Vec, } pub struct Surface { @@ -225,6 +227,7 @@ struct FramebufferAttachment { raw_image_flags: vk::ImageCreateFlags, view_usage: crate::TextureUses, view_format: wgt::TextureFormat, + raw_view_formats: Vec, } #[derive(Clone, Eq, Hash, PartialEq)] @@ -294,6 +297,7 @@ pub struct Texture { format_info: wgt::TextureFormatInfo, raw_flags: vk::ImageCreateFlags, copy_size: crate::CopyExtent, + view_formats: Vec, } impl Texture { From 8adf4ec3d7759b1da086bb4be78793b7ba9a59e6 Mon Sep 17 00:00:00 2001 From: Jinlei Li Date: Sat, 28 Jan 2023 23:09:34 +0800 Subject: [PATCH 2/2] Update CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index dcf255466b5..33c212b8bec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,6 +49,7 @@ Bottom level categories: #### Vulkan - Improve format MSAA capabilities detection. By @jinleili in [#3429](https://github.com/gfx-rs/wgpu/pull/3429) +- Fix surface view formats validation error. By @jinleili in [#3432](https://github.com/gfx-rs/wgpu/pull/3432) ## wgpu-0.15.0 (2023-01-25)