Fix unnecessarily strict validation for DRM format modifiers (#2469)

This commit is contained in:
Rua 2024-02-20 14:00:01 +01:00 committed by GitHub
parent c90c6e87c4
commit 4eb8111055
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -13,6 +13,8 @@ use super::{
ImageSubresourceLayers, ImageSubresourceRange, ImageTiling, ImageUsage, SampleCount, ImageSubresourceLayers, ImageSubresourceRange, ImageTiling, ImageUsage, SampleCount,
SparseImageMemoryRequirements, SubresourceLayout, SparseImageMemoryRequirements, SubresourceLayout,
}; };
#[cfg(doc)]
use crate::format::DrmFormatModifierProperties;
use crate::{ use crate::{
cache::OnceCache, cache::OnceCache,
device::{Device, DeviceOwned}, device::{Device, DeviceOwned},
@ -158,8 +160,19 @@ impl RawImage {
let format_list_view_formats_vk: Vec<_>; let format_list_view_formats_vk: Vec<_>;
let mut stencil_usage_info_vk = None; let mut stencil_usage_info_vk = None;
#[allow(clippy::comparison_chain)] if !drm_format_modifiers.is_empty() {
if drm_format_modifiers.len() == 1 { if drm_format_modifier_plane_layouts.is_empty() {
let next = drm_format_modifier_list_info_vk.insert(
ash::vk::ImageDrmFormatModifierListCreateInfoEXT {
drm_format_modifier_count: drm_format_modifiers.len() as u32,
p_drm_format_modifiers: drm_format_modifiers.as_ptr(),
..Default::default()
},
);
next.p_next = create_info_vk.p_next;
create_info_vk.p_next = next as *const _ as *const _;
} else {
drm_format_modifier_plane_layouts_vk = drm_format_modifier_plane_layouts drm_format_modifier_plane_layouts_vk = drm_format_modifier_plane_layouts
.iter() .iter()
.map(|subresource_layout| { .map(|subresource_layout| {
@ -193,17 +206,7 @@ impl RawImage {
next.p_next = create_info_vk.p_next; next.p_next = create_info_vk.p_next;
create_info_vk.p_next = next as *const _ as *const _; create_info_vk.p_next = next as *const _ as *const _;
} else if drm_format_modifiers.len() > 1 { }
let next = drm_format_modifier_list_info_vk.insert(
ash::vk::ImageDrmFormatModifierListCreateInfoEXT {
drm_format_modifier_count: drm_format_modifiers.len() as u32,
p_drm_format_modifiers: drm_format_modifiers.as_ptr(),
..Default::default()
},
);
next.p_next = create_info_vk.p_next;
create_info_vk.p_next = next as *const _ as *const _;
} }
if !external_memory_handle_types.is_empty() { if !external_memory_handle_types.is_empty() {
@ -1808,29 +1811,36 @@ pub struct ImageCreateInfo {
/// The default value is [`ImageLayout::Undefined`]. /// The default value is [`ImageLayout::Undefined`].
pub initial_layout: ImageLayout, pub initial_layout: ImageLayout,
/// The Linux DRM format modifiers that the image should be created with. /// A list of possible Linux DRM format modifiers that the image may be created with. If
/// `tiling` is [`ImageTiling::DrmFormatModifier`], then at least one DRM format modifier must
/// be provided. Otherwise, this must be empty.
/// ///
/// If this is not empty, then the /// If more than one DRM format modifier is provided, then the Vulkan driver will choose the
/// [`ext_image_drm_format_modifier`](crate::device::DeviceExtensions::ext_image_drm_format_modifier) /// modifier in an implementation-defined manner. You can query the modifier that has been
/// extension must be enabled on the device. /// chosen, after creating the image, by calling [`Image::drm_format_modifier`].
///
/// If exactly one DRM format modifier is provided, the image will always be created with that
/// modifier. You can then optionally specify the subresource layout of each memory plane with
/// the `drm_format_modifier_plane_layouts` field.
/// ///
/// The default value is empty. /// The default value is empty.
pub drm_format_modifiers: Vec<u64>, pub drm_format_modifiers: Vec<u64>,
/// If `drm_format_modifiers` contains one element, provides the subresource layouts of each /// If `drm_format_modifiers` contains exactly one element, optionally specifies an explicit
/// memory plane of the image. The number of elements must equal /// subresource layout for each memory plane of the image.
/// [`DrmFormatModifierProperties::drm_format_modifier_plane_count`], and the following ///
/// additional requirements apply to each element: /// If not empty, the number of provided subresource layouts must equal the number of memory
/// planes for `drm_format_modifiers[0]`, as reported by
/// [`DrmFormatModifierProperties::drm_format_modifier_plane_count`]. The following additional
/// requirements apply to each element:
/// - [`SubresourceLayout::size`] must always be 0. /// - [`SubresourceLayout::size`] must always be 0.
/// - If `array_layers` is 1, then [`SubresourceLayout::array_pitch`] must be `None`. /// - If `array_layers` is 1, then [`SubresourceLayout::array_pitch`] must be `None`.
/// - If `image_type` is not [`ImageType::Dim3d`] or `extent[2]` is 1, then /// - If `image_type` is not [`ImageType::Dim3d`] or `extent[2]` is 1, then
/// [`SubresourceLayout::depth_pitch`] must be `None`. /// [`SubresourceLayout::depth_pitch`] must be `None`.
/// ///
/// If `drm_format_modifiers` does not contain one element, then this must be empty. /// If `drm_format_modifiers` does not contain exactly one element, then this must be empty.
/// ///
/// The default value is empty. /// The default value is empty.
///
/// [`DrmFormatModifierProperties::drm_format_modifier_plane_count`]: crate::format::DrmFormatModifierProperties::drm_format_modifier_plane_count
pub drm_format_modifier_plane_layouts: Vec<SubresourceLayout>, pub drm_format_modifier_plane_layouts: Vec<SubresourceLayout>,
/// The external memory handle types that are going to be used with the image. /// The external memory handle types that are going to be used with the image.
@ -2683,19 +2693,17 @@ impl ImageCreateInfo {
} }
} }
if !drm_format_modifiers.is_empty() { if !(drm_format_modifier_plane_layouts.is_empty() || drm_format_modifiers.len() == 1) {
// This implicitly checks for the enabled extension too,
// so no need to check that separately.
if tiling != ImageTiling::DrmFormatModifier {
return Err(Box::new(ValidationError { return Err(Box::new(ValidationError {
problem: "`drm_format_modifiers` is not empty, but \ problem: "`drm_format_modifier_plane_layouts` is not empty, but \
`tiling` is not `ImageTiling::DrmFormatModifier`" `drm_format_modifiers` does not contain exactly one element"
.into(), .into(),
vuids: &["VUID-VkImageCreateInfo-pNext-02262"],
..Default::default() ..Default::default()
})); }));
} }
match (tiling, !drm_format_modifiers.is_empty()) {
(ImageTiling::DrmFormatModifier, true) => {
if flags.intersects(ImageCreateFlags::MUTABLE_FORMAT) && view_formats.is_empty() { if flags.intersects(ImageCreateFlags::MUTABLE_FORMAT) && view_formats.is_empty() {
return Err(Box::new(ValidationError { return Err(Box::new(ValidationError {
problem: "`tiling` is `ImageTiling::DrmFormatModifier`, and \ problem: "`tiling` is `ImageTiling::DrmFormatModifier`, and \
@ -2707,14 +2715,14 @@ impl ImageCreateInfo {
})); }));
} }
if drm_format_modifiers.len() == 1 { if !drm_format_modifier_plane_layouts.is_empty() {
let drm_format_modifier = drm_format_modifiers[0]; let drm_format_modifier = drm_format_modifiers[0];
let drm_format_modifier_properties = format_properties let drm_format_modifier_properties = format_properties
.drm_format_modifier_properties .drm_format_modifier_properties
.iter() .iter()
.find(|properties| properties.drm_format_modifier == drm_format_modifier) .find(|properties| properties.drm_format_modifier == drm_format_modifier)
.ok_or_else(|| Box::new(ValidationError { .ok_or_else(|| Box::new(ValidationError {
problem: "`drm_format_modifiers` has a length of 1, but \ problem: "`drm_format_modifier_plane_layouts` is not empty, but \
`drm_format_modifiers[0]` is not one of the modifiers in \ `drm_format_modifiers[0]` is not one of the modifiers in \
`FormatProperties::drm_format_properties`, as returned by \ `FormatProperties::drm_format_properties`, as returned by \
`PhysicalDevice::format_properties` for `format`".into(), `PhysicalDevice::format_properties` for `format`".into(),
@ -2726,11 +2734,12 @@ impl ImageCreateInfo {
!= drm_format_modifier_properties.drm_format_modifier_plane_count as usize != drm_format_modifier_properties.drm_format_modifier_plane_count as usize
{ {
return Err(Box::new(ValidationError { return Err(Box::new(ValidationError {
problem: "`drm_format_modifiers` has a length of 1, but the length of \ problem: "`drm_format_modifier_plane_layouts` is not empty, but the \
`drm_format_modifiers_plane_layouts` does not \ number of provided subresource layouts does not equal the number \
equal `DrmFormatModifierProperties::drm_format_modifier_plane_count` \ of memory planes for `drm_format_modifiers[0]`, specified in \
for `drm_format_modifiers[0]`, as returned by \ `DrmFormatModifierProperties::drm_format_modifier_plane_count`, \
`PhysicalDevice::format_properties` for `format`".into(), as returned by `PhysicalDevice::format_properties` for `format`"
.into(),
vuids: &["VUID-VkImageDrmFormatModifierExplicitCreateInfoEXT-drmFormatModifierPlaneCount-02265"], vuids: &["VUID-VkImageDrmFormatModifierExplicitCreateInfoEXT-drmFormatModifierPlaneCount-02265"],
..Default::default() ..Default::default()
})); }));
@ -2749,7 +2758,10 @@ impl ImageCreateInfo {
if size != 0 { if size != 0 {
return Err(Box::new(ValidationError { return Err(Box::new(ValidationError {
context: format!("drm_format_modifier_plane_layouts[{}].size", index) context: format!(
"drm_format_modifier_plane_layouts[{}].size",
index
)
.into(), .into(),
problem: "is not zero".into(), problem: "is not zero".into(),
vuids: &[ vuids: &[
@ -2785,36 +2797,30 @@ impl ImageCreateInfo {
})); }));
} }
} }
} else {
if !drm_format_modifier_plane_layouts.is_empty() {
return Err(Box::new(ValidationError {
problem: "`drm_format_modifiers` does not contain one element, but \
`drm_format_modifier_plane_layouts` is not empty"
.into(),
..Default::default()
}));
} }
} }
} else { (ImageTiling::DrmFormatModifier, false) => {
if tiling == ImageTiling::DrmFormatModifier {
return Err(Box::new(ValidationError { return Err(Box::new(ValidationError {
problem: "`tiling` is `ImageTiling::DrmFormatModifier`, but \ problem: "`tiling` is `ImageTiling::DrmFormatModifier`, but \
`drm_format_modifiers` is `None`" `drm_format_modifiers` is empty"
.into(), .into(),
vuids: &["VUID-VkImageCreateInfo-tiling-02261"], vuids: &["VUID-VkImageCreateInfo-tiling-02261"],
..Default::default() ..Default::default()
})); }));
} }
(_, true) => {
if !drm_format_modifier_plane_layouts.is_empty() { if tiling != ImageTiling::DrmFormatModifier {
return Err(Box::new(ValidationError { return Err(Box::new(ValidationError {
problem: "`drm_format_modifiers` does not contain one element, but \ problem: "`drm_format_modifiers` is not empty, but \
`drm_format_modifier_plane_layouts` is not empty" `tiling` is not `ImageTiling::DrmFormatModifier`"
.into(), .into(),
vuids: &["VUID-VkImageCreateInfo-pNext-02262"],
..Default::default() ..Default::default()
})); }));
} }
} }
(_, false) => (),
}
if !external_memory_handle_types.is_empty() { if !external_memory_handle_types.is_empty() {
if !(device.api_version() >= Version::V1_1 if !(device.api_version() >= Version::V1_1