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,52 +160,53 @@ 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() {
drm_format_modifier_plane_layouts_vk = drm_format_modifier_plane_layouts let next = drm_format_modifier_list_info_vk.insert(
.iter() ash::vk::ImageDrmFormatModifierListCreateInfoEXT {
.map(|subresource_layout| { drm_format_modifier_count: drm_format_modifiers.len() as u32,
let &SubresourceLayout { p_drm_format_modifiers: drm_format_modifiers.as_ptr(),
offset, ..Default::default()
size, },
row_pitch, );
array_pitch,
depth_pitch,
} = subresource_layout;
ash::vk::SubresourceLayout { next.p_next = create_info_vk.p_next;
offset, create_info_vk.p_next = next as *const _ as *const _;
size, } else {
row_pitch, drm_format_modifier_plane_layouts_vk = drm_format_modifier_plane_layouts
array_pitch: array_pitch.unwrap_or(0), .iter()
depth_pitch: depth_pitch.unwrap_or(0), .map(|subresource_layout| {
} let &SubresourceLayout {
}) offset,
.collect(); size,
row_pitch,
array_pitch,
depth_pitch,
} = subresource_layout;
let next = drm_format_modifier_explicit_info_vk.insert( ash::vk::SubresourceLayout {
ash::vk::ImageDrmFormatModifierExplicitCreateInfoEXT { offset,
drm_format_modifier: drm_format_modifiers[0], size,
drm_format_modifier_plane_count: drm_format_modifier_plane_layouts_vk.len() row_pitch,
as u32, array_pitch: array_pitch.unwrap_or(0),
p_plane_layouts: drm_format_modifier_plane_layouts_vk.as_ptr(), depth_pitch: depth_pitch.unwrap_or(0),
..Default::default() }
}, })
); .collect();
next.p_next = create_info_vk.p_next; let next = drm_format_modifier_explicit_info_vk.insert(
create_info_vk.p_next = next as *const _ as *const _; ash::vk::ImageDrmFormatModifierExplicitCreateInfoEXT {
} else if drm_format_modifiers.len() > 1 { drm_format_modifier: drm_format_modifiers[0],
let next = drm_format_modifier_list_info_vk.insert( drm_format_modifier_plane_count: drm_format_modifier_plane_layouts_vk.len()
ash::vk::ImageDrmFormatModifierListCreateInfoEXT { as u32,
drm_format_modifier_count: drm_format_modifiers.len() as u32, p_plane_layouts: drm_format_modifier_plane_layouts_vk.as_ptr(),
p_drm_format_modifiers: drm_format_modifiers.as_ptr(), ..Default::default()
..Default::default() },
}, );
);
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 _;
}
} }
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,137 +2693,133 @@ 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, return Err(Box::new(ValidationError {
// so no need to check that separately. problem: "`drm_format_modifier_plane_layouts` is not empty, but \
if tiling != ImageTiling::DrmFormatModifier { `drm_format_modifiers` does not contain exactly one element"
return Err(Box::new(ValidationError { .into(),
problem: "`drm_format_modifiers` is not empty, but \ ..Default::default()
`tiling` is not `ImageTiling::DrmFormatModifier`" }));
.into(), }
vuids: &["VUID-VkImageCreateInfo-pNext-02262"],
..Default::default()
}));
}
if flags.intersects(ImageCreateFlags::MUTABLE_FORMAT) && view_formats.is_empty() { match (tiling, !drm_format_modifiers.is_empty()) {
return Err(Box::new(ValidationError { (ImageTiling::DrmFormatModifier, true) => {
problem: "`tiling` is `ImageTiling::DrmFormatModifier`, and \ if flags.intersects(ImageCreateFlags::MUTABLE_FORMAT) && view_formats.is_empty() {
`flags` contains `ImageCreateFlags::MUTABLE_FORMAT`, but \
`view_formats` is empty"
.into(),
vuids: &["VUID-VkImageCreateInfo-tiling-02353"],
..Default::default()
}));
}
if drm_format_modifiers.len() == 1 {
let drm_format_modifier = drm_format_modifiers[0];
let drm_format_modifier_properties = format_properties
.drm_format_modifier_properties
.iter()
.find(|properties| properties.drm_format_modifier == drm_format_modifier)
.ok_or_else(|| Box::new(ValidationError {
problem: "`drm_format_modifiers` has a length of 1, but \
`drm_format_modifiers[0]` is not one of the modifiers in \
`FormatProperties::drm_format_properties`, as returned by \
`PhysicalDevice::format_properties` for `format`".into(),
vuids: &["VUID-VkImageDrmFormatModifierExplicitCreateInfoEXT-drmFormatModifierPlaneCount-02265"],
..Default::default()
}))?;
if drm_format_modifier_plane_layouts.len()
!= 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: "`tiling` is `ImageTiling::DrmFormatModifier`, and \
`drm_format_modifiers_plane_layouts` does not \ `flags` contains `ImageCreateFlags::MUTABLE_FORMAT`, but \
equal `DrmFormatModifierProperties::drm_format_modifier_plane_count` \ `view_formats` is empty"
for `drm_format_modifiers[0]`, as returned by \ .into(),
`PhysicalDevice::format_properties` for `format`".into(), vuids: &["VUID-VkImageCreateInfo-tiling-02353"],
vuids: &["VUID-VkImageDrmFormatModifierExplicitCreateInfoEXT-drmFormatModifierPlaneCount-02265"],
..Default::default() ..Default::default()
})); }));
} }
for (index, subresource_layout) in
drm_format_modifier_plane_layouts.iter().enumerate()
{
let &SubresourceLayout {
offset: _,
size,
row_pitch: _,
array_pitch,
depth_pitch,
} = subresource_layout;
if size != 0 {
return Err(Box::new(ValidationError {
context: format!("drm_format_modifier_plane_layouts[{}].size", index)
.into(),
problem: "is not zero".into(),
vuids: &[
"VUID-VkImageDrmFormatModifierExplicitCreateInfoEXT-size-02267",
],
..Default::default()
}));
}
if array_layers == 1 && array_pitch.is_some() {
return Err(Box::new(ValidationError {
problem: format!(
"`array_layers` is 1, but \
`drm_format_modifier_plane_layouts[{}].array_pitch` is `Some`",
index
)
.into(),
vuids: &["VUID-VkImageDrmFormatModifierExplicitCreateInfoEXT-arrayPitch-02268"],
..Default::default()
}));
}
if extent[2] == 1 && depth_pitch.is_some() {
return Err(Box::new(ValidationError {
problem: format!(
"`extent[2]` is 1, but \
`drm_format_modifier_plane_layouts[{}].depth_pitch` is `Some`",
index
)
.into(),
vuids: &["VUID-VkImageDrmFormatModifierExplicitCreateInfoEXT-depthPitch-02269"],
..Default::default()
}));
}
}
} else {
if !drm_format_modifier_plane_layouts.is_empty() { if !drm_format_modifier_plane_layouts.is_empty() {
return Err(Box::new(ValidationError { let drm_format_modifier = drm_format_modifiers[0];
problem: "`drm_format_modifiers` does not contain one element, but \ let drm_format_modifier_properties = format_properties
`drm_format_modifier_plane_layouts` is not empty" .drm_format_modifier_properties
.into(), .iter()
..Default::default() .find(|properties| properties.drm_format_modifier == drm_format_modifier)
})); .ok_or_else(|| Box::new(ValidationError {
problem: "`drm_format_modifier_plane_layouts` is not empty, but \
`drm_format_modifiers[0]` is not one of the modifiers in \
`FormatProperties::drm_format_properties`, as returned by \
`PhysicalDevice::format_properties` for `format`".into(),
vuids: &["VUID-VkImageDrmFormatModifierExplicitCreateInfoEXT-drmFormatModifierPlaneCount-02265"],
..Default::default()
}))?;
if drm_format_modifier_plane_layouts.len()
!= drm_format_modifier_properties.drm_format_modifier_plane_count as usize
{
return Err(Box::new(ValidationError {
problem: "`drm_format_modifier_plane_layouts` is not empty, but the \
number of provided subresource layouts does not equal the number \
of memory planes for `drm_format_modifiers[0]`, specified in \
`DrmFormatModifierProperties::drm_format_modifier_plane_count`, \
as returned by `PhysicalDevice::format_properties` for `format`"
.into(),
vuids: &["VUID-VkImageDrmFormatModifierExplicitCreateInfoEXT-drmFormatModifierPlaneCount-02265"],
..Default::default()
}));
}
for (index, subresource_layout) in
drm_format_modifier_plane_layouts.iter().enumerate()
{
let &SubresourceLayout {
offset: _,
size,
row_pitch: _,
array_pitch,
depth_pitch,
} = subresource_layout;
if size != 0 {
return Err(Box::new(ValidationError {
context: format!(
"drm_format_modifier_plane_layouts[{}].size",
index
)
.into(),
problem: "is not zero".into(),
vuids: &[
"VUID-VkImageDrmFormatModifierExplicitCreateInfoEXT-size-02267",
],
..Default::default()
}));
}
if array_layers == 1 && array_pitch.is_some() {
return Err(Box::new(ValidationError {
problem: format!(
"`array_layers` is 1, but \
`drm_format_modifier_plane_layouts[{}].array_pitch` is `Some`",
index
)
.into(),
vuids: &["VUID-VkImageDrmFormatModifierExplicitCreateInfoEXT-arrayPitch-02268"],
..Default::default()
}));
}
if extent[2] == 1 && depth_pitch.is_some() {
return Err(Box::new(ValidationError {
problem: format!(
"`extent[2]` is 1, but \
`drm_format_modifier_plane_layouts[{}].depth_pitch` is `Some`",
index
)
.into(),
vuids: &["VUID-VkImageDrmFormatModifierExplicitCreateInfoEXT-depthPitch-02269"],
..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(),
..Default::default() vuids: &["VUID-VkImageCreateInfo-pNext-02262"],
})); ..Default::default()
}));
}
} }
(_, false) => (),
} }
if !external_memory_handle_types.is_empty() { if !external_memory_handle_types.is_empty() {