Add validation for VkExportMemoryAllocateInfo (#2258)

* Add validation for `VkExportMemoryAllocateInfo`

* Fix oopsie
This commit is contained in:
marc0246 2023-07-10 12:36:57 +02:00 committed by GitHub
parent 3ae450ada0
commit c0bc610037
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 215 additions and 58 deletions

View File

@ -890,18 +890,19 @@ vulkan_bitflags! {
},*/
}
/// The buffer configuration to query in
/// [`PhysicalDevice::external_buffer_properties`](crate::device::physical::PhysicalDevice::external_buffer_properties).
/// The buffer configuration to query in [`PhysicalDevice::external_buffer_properties`].
///
/// [`PhysicalDevice::external_buffer_properties`]: crate::device::physical::PhysicalDevice::external_buffer_properties
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct ExternalBufferInfo {
/// The external handle type that will be used with the buffer.
pub handle_type: ExternalMemoryHandleType,
/// The flags that will be used.
pub flags: BufferCreateFlags,
/// The usage that the buffer will have.
pub usage: BufferUsage,
/// The sparse binding parameters that will be used.
pub sparse: Option<BufferCreateFlags>,
/// The external handle type that will be used with the buffer.
pub handle_type: ExternalMemoryHandleType,
pub _ne: crate::NonExhaustive,
}
@ -911,9 +912,9 @@ impl ExternalBufferInfo {
#[inline]
pub fn handle_type(handle_type: ExternalMemoryHandleType) -> Self {
Self {
handle_type,
flags: BufferCreateFlags::empty(),
usage: BufferUsage::empty(),
sparse: None,
handle_type,
_ne: crate::NonExhaustive(()),
}
}
@ -923,12 +924,20 @@ impl ExternalBufferInfo {
physical_device: &PhysicalDevice,
) -> Result<(), Box<ValidationError>> {
let &Self {
handle_type,
flags,
usage,
sparse: _,
handle_type,
_ne: _,
} = self;
flags
.validate_physical_device(physical_device)
.map_err(|err| ValidationError {
context: "flags".into(),
vuids: &["VUID-VkPhysicalDeviceExternalBufferInfo-flags-parameter"],
..ValidationError::from_requirement(err)
})?;
usage
.validate_physical_device(physical_device)
.map_err(|err| ValidationError {

View File

@ -15,6 +15,7 @@
use super::{Buffer, BufferCreateFlags, BufferMemory, BufferUsage};
use crate::{
buffer::ExternalBufferInfo,
device::{Device, DeviceOwned},
instance::InstanceOwnedDebugWrapper,
macros::impl_id_counter,
@ -289,14 +290,13 @@ impl RawBuffer {
fn validate_bind_memory(&self, allocation: &MemoryAlloc) -> Result<(), Box<ValidationError>> {
assert_ne!(allocation.allocation_type(), AllocationType::NonLinear);
let physical_device = self.device().physical_device();
let memory_requirements = &self.memory_requirements;
let memory = allocation.device_memory();
let memory_offset = allocation.offset();
let memory_type = &self
.device
.physical_device()
.memory_properties()
.memory_types[memory.memory_type_index() as usize];
let memory_type =
&physical_device.memory_properties().memory_types[memory.memory_type_index() as usize];
// VUID-VkBindBufferMemoryInfo-commonparent
assert_eq!(self.device(), memory.device());
@ -380,19 +380,86 @@ impl RawBuffer {
}));
}
if !memory.export_handle_types().is_empty()
&& !self
if !memory.export_handle_types().is_empty() {
if !self
.external_memory_handle_types
.intersects(memory.export_handle_types())
{
return Err(Box::new(ValidationError {
problem: "`allocation.device_memory().export_handle_types()` is not empty, but \
it does not share at least one memory type with \
`self.external_memory_handle_types()`"
.into(),
vuids: &["VUID-VkBindBufferMemoryInfo-memory-02726"],
..Default::default()
}));
{
return Err(Box::new(ValidationError {
problem:
"`allocation.device_memory().export_handle_types()` is not empty, but \
it does not share at least one handle type with \
`self.external_memory_handle_types()`"
.into(),
vuids: &["VUID-VkBindBufferMemoryInfo-memory-02726"],
..Default::default()
}));
}
for handle_type in memory.export_handle_types() {
let external_buffer_properties = unsafe {
physical_device.external_buffer_properties_unchecked(ExternalBufferInfo {
flags: self.flags,
usage: self.usage,
handle_type,
_ne: crate::NonExhaustive(()),
})
};
if external_buffer_properties
.external_memory_properties
.dedicated_only
&& !memory.is_dedicated()
{
return Err(Box::new(ValidationError {
problem: format!(
"`allocation.device_memory().export_handle_types()` has the `{:?}` \
flag set, which requires a dedicated allocation as returned by \
`PhysicalDevice::external_buffer_properties`, but \
`allocation.device_memory()` is not a dedicated allocation",
handle_type,
)
.into(),
vuids: &["VUID-VkMemoryAllocateInfo-pNext-00639"],
..Default::default()
}));
}
if !external_buffer_properties
.external_memory_properties
.exportable
{
return Err(Box::new(ValidationError {
problem: format!(
"`allocation.device_memory().export_handle_types()` has the `{:?}` \
flag set, but the flag is not supported for exporting, as returned by \
`PhysicalDevice::external_buffer_properties`",
handle_type,
)
.into(),
vuids: &["VUID-VkExportMemoryAllocateInfo-handleTypes-00656"],
..Default::default()
}));
}
if !external_buffer_properties
.external_memory_properties
.compatible_handle_types
.contains(memory.export_handle_types())
{
return Err(Box::new(ValidationError {
problem: format!(
"`allocation.device_memory().export_handle_types()` has the `{:?}` \
flag set, but the flag is not compatible with the other flags set, as \
returned by `PhysicalDevice::external_buffer_properties`",
handle_type,
)
.into(),
vuids: &["VUID-VkExportMemoryAllocateInfo-handleTypes-00656"],
..Default::default()
}));
}
}
}
if let Some(handle_type) = memory.imported_handle_type() {

View File

@ -538,14 +538,14 @@ impl PhysicalDevice {
/* Input */
let &ExternalBufferInfo {
handle_type,
flags,
usage,
sparse,
handle_type,
_ne: _,
} = info;
let external_buffer_info = ash::vk::PhysicalDeviceExternalBufferInfo {
flags: sparse.map(Into::into).unwrap_or_default(),
flags: flags.into(),
usage: usage.into(),
handle_type: handle_type.into(),
..Default::default()

View File

@ -730,6 +730,8 @@ impl RawImage {
&self,
allocations: &[MemoryAlloc],
) -> Result<(), Box<ValidationError>> {
let physical_device = self.device().physical_device();
if self.flags.intersects(ImageCreateFlags::DISJOINT) {
match self.tiling {
ImageTiling::Optimal | ImageTiling::Linear => {
@ -768,7 +770,8 @@ impl RawImage {
}
}
for (index, (allocation, memory_requirements)) in (allocations.iter())
for (index, (allocation, memory_requirements)) in allocations
.iter()
.zip(self.memory_requirements.iter())
.enumerate()
{
@ -807,11 +810,8 @@ impl RawImage {
let memory = allocation.device_memory();
let memory_offset = allocation.offset();
let memory_type = &self
.device
.physical_device()
.memory_properties()
.memory_types[memory.memory_type_index() as usize];
let memory_type = &physical_device.memory_properties().memory_types
[memory.memory_type_index() as usize];
// VUID-VkBindImageMemoryInfo-commonparent
assert_eq!(self.device(), memory.device());
@ -924,22 +924,106 @@ impl RawImage {
}));
}
if !memory.export_handle_types().is_empty()
&& !memory
.export_handle_types()
.intersects(self.external_memory_handle_types)
{
return Err(Box::new(ValidationError {
problem: format!(
"`allocations[{}].device_memory().export_handle_types()` is not empty, \
but it does not share at least one memory type with \
`self.external_memory_handle_types()`",
index
)
.into(),
vuids: &["VUID-VkBindImageMemoryInfo-memory-02728"],
..Default::default()
}));
if !memory.export_handle_types().is_empty() {
if !self
.external_memory_handle_types
.intersects(memory.export_handle_types())
{
return Err(Box::new(ValidationError {
problem: format!(
"`allocations[{}].device_memory().export_handle_types()` is not empty, \
but it does not share at least one memory type with \
`self.external_memory_handle_types()`",
index
)
.into(),
vuids: &["VUID-VkBindImageMemoryInfo-memory-02728"],
..Default::default()
}));
}
for handle_type in memory.export_handle_types() {
let image_format_properties = unsafe {
physical_device.image_format_properties_unchecked(ImageFormatInfo {
flags: self.flags,
format: self.format,
image_type: self.image_type,
tiling: self.tiling,
usage: self.usage,
stencil_usage: self.stencil_usage,
external_memory_handle_type: Some(handle_type),
image_view_type: None,
drm_format_modifier_info: self.drm_format_modifier().map(
|(drm_format_modifier, _)| ImageDrmFormatModifierInfo {
drm_format_modifier,
sharing: self.sharing.clone(),
_ne: crate::NonExhaustive(()),
},
),
_ne: crate::NonExhaustive(()),
})
}
.map_err(|_| ValidationError {
problem: "`PhysicalDevice::image_format_properties` returned an error"
.into(),
..Default::default()
})?
.unwrap();
if image_format_properties
.external_memory_properties
.dedicated_only
&& !memory.is_dedicated()
{
return Err(Box::new(ValidationError {
problem: format!(
"`allocations[{}].device_memory().export_handle_types()` has the \
`{:?}` flag set, which requires a dedicated allocation as returned \
by `PhysicalDevice::image_format_properties`, but \
`allocations[{}].device_memory()` is not a dedicated allocation",
index, handle_type, index,
)
.into(),
vuids: &["VUID-VkMemoryAllocateInfo-pNext-00639"],
..Default::default()
}));
}
if !image_format_properties
.external_memory_properties
.exportable
{
return Err(Box::new(ValidationError {
problem: format!(
"`allocations[{}].device_memory().export_handle_types()` has the \
`{:?}` flag set, but the flag is not supported for exporting, as \
returned by `PhysicalDevice::image_format_properties`",
index, handle_type,
)
.into(),
vuids: &["VUID-VkExportMemoryAllocateInfo-handleTypes-00656"],
..Default::default()
}));
}
if !image_format_properties
.external_memory_properties
.compatible_handle_types
.contains(memory.export_handle_types())
{
return Err(Box::new(ValidationError {
problem: format!(
"`allocation.device_memory().export_handle_types()` has the `{:?}` \
flag set, but the flag is not compatible with the other flags set, \
as returned by `PhysicalDevice::image_format_properties`",
handle_type,
)
.into(),
vuids: &["VUID-VkExportMemoryAllocateInfo-handleTypes-00656"],
..Default::default()
}));
}
}
}
if let Some(handle_type) = memory.imported_handle_type() {
@ -2397,8 +2481,7 @@ impl ImageCreateInfo {
}));
}
let queue_family_count =
device.physical_device().queue_family_properties().len() as u32;
let queue_family_count = physical_device.queue_family_properties().len() as u32;
for (index, &queue_family_index) in queue_family_indices.iter().enumerate() {
if queue_family_indices[..index].contains(&queue_family_index) {
@ -2611,8 +2694,7 @@ impl ImageCreateInfo {
for drm_format_modifier in iter_or_none(drm_format_modifiers.iter().copied()) {
for external_memory_handle_type in iter_or_none(external_memory_handle_types) {
let image_format_properties = unsafe {
device
.physical_device()
physical_device
.image_format_properties_unchecked(ImageFormatInfo {
flags,
format: Some(format),

View File

@ -743,9 +743,8 @@ impl<'d> MemoryAllocateInfo<'d> {
// VUID-VkMemoryAllocateInfo-pNext-00639
// VUID-VkExportMemoryAllocateInfo-handleTypes-00656
// TODO: how do you fullfill this when you don't know the image or buffer parameters?
// Does exporting memory require specifying these parameters up front, and does it tie
// the allocation to only images or buffers of that type?
// Impossible to validate here, instead this is validated in `RawBuffer::bind_memory`
// and `RawImage::bind_memory`.
}
if !flags.is_empty() {