Use actual integer bitflags for Vulkan bitflag types (#2073)

* Use actual integer bitflags for Vulkan bitflag types

* Fix doc tests

* Fix Fence and Semaphore on Win32 and Fuchsia

* Add macro for bitflags that have a corresponding enum

* Fix bug
This commit is contained in:
Rua 2022-11-05 06:02:28 +01:00 committed by GitHub
parent 05746e8f75
commit a984a925c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
125 changed files with 4015 additions and 5089 deletions

View File

@ -23,6 +23,7 @@ use vulkano::{
}, },
device::{ device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
QueueFlags,
}, },
instance::{Instance, InstanceCreateInfo}, instance::{Instance, InstanceCreateInfo},
memory::allocator::StandardMemoryAllocator, memory::allocator::StandardMemoryAllocator,
@ -58,7 +59,7 @@ fn main() {
// that supports compute operations. // that supports compute operations.
p.queue_family_properties() p.queue_family_properties()
.iter() .iter()
.position(|q| q.queue_flags.compute) .position(|q| q.queue_flags.intersects(QueueFlags::COMPUTE))
.map(|i| (p, i as u32)) .map(|i| (p, i as u32))
}) })
.min_by_key(|(p, _)| match p.properties().device_type { .min_by_key(|(p, _)| match p.properties().device_type {
@ -157,10 +158,7 @@ fn main() {
// Builds the buffer and fills it with this iterator. // Builds the buffer and fills it with this iterator.
CpuAccessibleBuffer::from_iter( CpuAccessibleBuffer::from_iter(
&memory_allocator, &memory_allocator,
BufferUsage { BufferUsage::STORAGE_BUFFER,
storage_buffer: true,
..BufferUsage::empty()
},
false, false,
data_iter, data_iter,
) )

View File

@ -32,6 +32,7 @@ use vulkano::{
}, },
device::{ device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
QueueFlags,
}, },
image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage}, image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage},
impl_vertex, impl_vertex,
@ -99,7 +100,8 @@ fn main() {
.iter() .iter()
.enumerate() .enumerate()
.position(|(i, q)| { .position(|(i, q)| {
q.queue_flags.graphics && p.surface_support(i as u32, &surface).unwrap_or(false) q.queue_flags.intersects(QueueFlags::GRAPHICS)
&& p.surface_support(i as u32, &surface).unwrap_or(false)
}) })
.map(|i| (p, i as u32)) .map(|i| (p, i as u32))
}) })
@ -155,13 +157,10 @@ fn main() {
min_image_count: surface_capabilities.min_image_count, min_image_count: surface_capabilities.min_image_count,
image_format, image_format,
image_extent: window.inner_size().into(), image_extent: window.inner_size().into(),
image_usage: ImageUsage { image_usage: ImageUsage::COLOR_ATTACHMENT,
color_attachment: true,
..ImageUsage::empty()
},
composite_alpha: surface_capabilities composite_alpha: surface_capabilities
.supported_composite_alpha .supported_composite_alpha
.iter() .into_iter()
.next() .next()
.unwrap(), .unwrap(),
..Default::default() ..Default::default()

View File

@ -15,6 +15,7 @@ use vulkano::{
}, },
device::{ device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
QueueFlags,
}, },
image::{view::ImageView, ImageUsage, SwapchainImage}, image::{view::ImageView, ImageUsage, SwapchainImage},
instance::{Instance, InstanceCreateInfo}, instance::{Instance, InstanceCreateInfo},
@ -68,7 +69,8 @@ fn main() {
.iter() .iter()
.enumerate() .enumerate()
.position(|(i, q)| { .position(|(i, q)| {
q.queue_flags.graphics && p.surface_support(i as u32, &surface).unwrap_or(false) q.queue_flags.intersects(QueueFlags::GRAPHICS)
&& p.surface_support(i as u32, &surface).unwrap_or(false)
}) })
.map(|i| (p, i as u32)) .map(|i| (p, i as u32))
}) })
@ -123,13 +125,10 @@ fn main() {
min_image_count: surface_capabilities.min_image_count, min_image_count: surface_capabilities.min_image_count,
image_format, image_format,
image_extent: window.inner_size().into(), image_extent: window.inner_size().into(),
image_usage: ImageUsage { image_usage: ImageUsage::COLOR_ATTACHMENT,
color_attachment: true,
..ImageUsage::empty()
},
composite_alpha: surface_capabilities composite_alpha: surface_capabilities
.supported_composite_alpha .supported_composite_alpha
.iter() .into_iter()
.next() .next()
.unwrap(), .unwrap(),
..Default::default() ..Default::default()

View File

@ -87,37 +87,31 @@ fn main() {
DebugUtilsMessenger::new( DebugUtilsMessenger::new(
instance.clone(), instance.clone(),
DebugUtilsMessengerCreateInfo { DebugUtilsMessengerCreateInfo {
message_severity: DebugUtilsMessageSeverity { message_severity: DebugUtilsMessageSeverity::ERROR
error: true, | DebugUtilsMessageSeverity::WARNING
warning: true, | DebugUtilsMessageSeverity::INFO
information: true, | DebugUtilsMessageSeverity::VERBOSE,
verbose: true, message_type: DebugUtilsMessageType::GENERAL
..DebugUtilsMessageSeverity::empty() | DebugUtilsMessageType::VALIDATION
}, | DebugUtilsMessageType::PERFORMANCE,
message_type: DebugUtilsMessageType {
general: true,
validation: true,
performance: true,
..DebugUtilsMessageType::empty()
},
..DebugUtilsMessengerCreateInfo::user_callback(Arc::new(|msg| { ..DebugUtilsMessengerCreateInfo::user_callback(Arc::new(|msg| {
let severity = if msg.severity.error { let severity = if msg.severity.intersects(DebugUtilsMessageSeverity::ERROR) {
"error" "error"
} else if msg.severity.warning { } else if msg.severity.intersects(DebugUtilsMessageSeverity::WARNING) {
"warning" "warning"
} else if msg.severity.information { } else if msg.severity.intersects(DebugUtilsMessageSeverity::INFO) {
"information" "information"
} else if msg.severity.verbose { } else if msg.severity.intersects(DebugUtilsMessageSeverity::VERBOSE) {
"verbose" "verbose"
} else { } else {
panic!("no-impl"); panic!("no-impl");
}; };
let ty = if msg.ty.general { let ty = if msg.ty.intersects(DebugUtilsMessageType::GENERAL) {
"general" "general"
} else if msg.ty.validation { } else if msg.ty.intersects(DebugUtilsMessageType::VALIDATION) {
"validation" "validation"
} else if msg.ty.performance { } else if msg.ty.intersects(DebugUtilsMessageType::PERFORMANCE) {
"performance" "performance"
} else { } else {
panic!("no-impl"); panic!("no-impl");

View File

@ -69,10 +69,7 @@ impl AmbientLightingSystem {
let vertex_buffer = { let vertex_buffer = {
CpuAccessibleBuffer::from_iter( CpuAccessibleBuffer::from_iter(
memory_allocator, memory_allocator,
BufferUsage { BufferUsage::VERTEX_BUFFER,
vertex_buffer: true,
..BufferUsage::empty()
},
false, false,
vertices, vertices,
) )

View File

@ -70,10 +70,7 @@ impl DirectionalLightingSystem {
let vertex_buffer = { let vertex_buffer = {
CpuAccessibleBuffer::from_iter( CpuAccessibleBuffer::from_iter(
memory_allocator, memory_allocator,
BufferUsage { BufferUsage::VERTEX_BUFFER,
vertex_buffer: true,
..BufferUsage::empty()
},
false, false,
vertices, vertices,
) )

View File

@ -69,10 +69,7 @@ impl PointLightingSystem {
let vertex_buffer = { let vertex_buffer = {
CpuAccessibleBuffer::from_iter( CpuAccessibleBuffer::from_iter(
memory_allocator, memory_allocator,
BufferUsage { BufferUsage::VERTEX_BUFFER,
vertex_buffer: true,
..BufferUsage::empty()
},
false, false,
vertices, vertices,
) )

View File

@ -158,11 +158,7 @@ impl FrameSystem {
&memory_allocator, &memory_allocator,
[1, 1], [1, 1],
Format::A2B10G10R10_UNORM_PACK32, Format::A2B10G10R10_UNORM_PACK32,
ImageUsage { ImageUsage::TRANSIENT_ATTACHMENT | ImageUsage::INPUT_ATTACHMENT,
transient_attachment: true,
input_attachment: true,
..ImageUsage::empty()
},
) )
.unwrap(), .unwrap(),
) )
@ -172,11 +168,7 @@ impl FrameSystem {
&memory_allocator, &memory_allocator,
[1, 1], [1, 1],
Format::R16G16B16A16_SFLOAT, Format::R16G16B16A16_SFLOAT,
ImageUsage { ImageUsage::TRANSIENT_ATTACHMENT | ImageUsage::INPUT_ATTACHMENT,
transient_attachment: true,
input_attachment: true,
..ImageUsage::empty()
},
) )
.unwrap(), .unwrap(),
) )
@ -186,11 +178,7 @@ impl FrameSystem {
&memory_allocator, &memory_allocator,
[1, 1], [1, 1],
Format::D16_UNORM, Format::D16_UNORM,
ImageUsage { ImageUsage::TRANSIENT_ATTACHMENT | ImageUsage::INPUT_ATTACHMENT,
transient_attachment: true,
input_attachment: true,
..ImageUsage::empty()
},
) )
.unwrap(), .unwrap(),
) )
@ -280,11 +268,7 @@ impl FrameSystem {
&self.memory_allocator, &self.memory_allocator,
img_dims, img_dims,
Format::A2B10G10R10_UNORM_PACK32, Format::A2B10G10R10_UNORM_PACK32,
ImageUsage { ImageUsage::TRANSIENT_ATTACHMENT | ImageUsage::INPUT_ATTACHMENT,
transient_attachment: true,
input_attachment: true,
..ImageUsage::empty()
},
) )
.unwrap(), .unwrap(),
) )
@ -294,11 +278,7 @@ impl FrameSystem {
&self.memory_allocator, &self.memory_allocator,
img_dims, img_dims,
Format::R16G16B16A16_SFLOAT, Format::R16G16B16A16_SFLOAT,
ImageUsage { ImageUsage::TRANSIENT_ATTACHMENT | ImageUsage::INPUT_ATTACHMENT,
transient_attachment: true,
input_attachment: true,
..ImageUsage::empty()
},
) )
.unwrap(), .unwrap(),
) )
@ -308,11 +288,7 @@ impl FrameSystem {
&self.memory_allocator, &self.memory_allocator,
img_dims, img_dims,
Format::D16_UNORM, Format::D16_UNORM,
ImageUsage { ImageUsage::TRANSIENT_ATTACHMENT | ImageUsage::INPUT_ATTACHMENT,
transient_attachment: true,
input_attachment: true,
..ImageUsage::empty()
},
) )
.unwrap(), .unwrap(),
) )

View File

@ -35,6 +35,7 @@ use vulkano::{
command_buffer::allocator::StandardCommandBufferAllocator, command_buffer::allocator::StandardCommandBufferAllocator,
device::{ device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
QueueFlags,
}, },
image::{view::ImageView, ImageUsage}, image::{view::ImageView, ImageUsage},
instance::{Instance, InstanceCreateInfo}, instance::{Instance, InstanceCreateInfo},
@ -90,7 +91,8 @@ fn main() {
.iter() .iter()
.enumerate() .enumerate()
.position(|(i, q)| { .position(|(i, q)| {
q.queue_flags.graphics && p.surface_support(i as u32, &surface).unwrap_or(false) q.queue_flags.intersects(QueueFlags::GRAPHICS)
&& p.surface_support(i as u32, &surface).unwrap_or(false)
}) })
.map(|i| (p, i as u32)) .map(|i| (p, i as u32))
}) })
@ -145,13 +147,10 @@ fn main() {
min_image_count: surface_capabilities.min_image_count, min_image_count: surface_capabilities.min_image_count,
image_format, image_format,
image_extent: window.inner_size().into(), image_extent: window.inner_size().into(),
image_usage: ImageUsage { image_usage: ImageUsage::COLOR_ATTACHMENT,
color_attachment: true,
..ImageUsage::empty()
},
composite_alpha: surface_capabilities composite_alpha: surface_capabilities
.supported_composite_alpha .supported_composite_alpha
.iter() .into_iter()
.next() .next()
.unwrap(), .unwrap(),
..Default::default() ..Default::default()

View File

@ -60,10 +60,7 @@ impl TriangleDrawSystem {
let vertex_buffer = { let vertex_buffer = {
CpuAccessibleBuffer::from_iter( CpuAccessibleBuffer::from_iter(
memory_allocator, memory_allocator,
BufferUsage { BufferUsage::VERTEX_BUFFER,
vertex_buffer: true,
..BufferUsage::empty()
},
false, false,
vertices, vertices,
) )

View File

@ -26,6 +26,7 @@ use vulkano::{
}, },
device::{ device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
QueueFlags,
}, },
instance::{Instance, InstanceCreateInfo}, instance::{Instance, InstanceCreateInfo},
memory::allocator::StandardMemoryAllocator, memory::allocator::StandardMemoryAllocator,
@ -57,7 +58,7 @@ fn main() {
.filter_map(|p| { .filter_map(|p| {
p.queue_family_properties() p.queue_family_properties()
.iter() .iter()
.position(|q| q.queue_flags.compute) .position(|q| q.queue_flags.intersects(QueueFlags::COMPUTE))
.map(|i| (p, i as u32)) .map(|i| (p, i as u32))
}) })
.min_by_key(|(p, _)| match p.properties().device_type { .min_by_key(|(p, _)| match p.properties().device_type {
@ -168,10 +169,7 @@ fn main() {
let input_buffer = CpuAccessibleBuffer::from_iter( let input_buffer = CpuAccessibleBuffer::from_iter(
&memory_allocator, &memory_allocator,
BufferUsage { BufferUsage::UNIFORM_BUFFER,
uniform_buffer: true,
..BufferUsage::empty()
},
false, false,
aligned_data.into_iter(), aligned_data.into_iter(),
) )
@ -179,10 +177,7 @@ fn main() {
let output_buffer = CpuAccessibleBuffer::from_iter( let output_buffer = CpuAccessibleBuffer::from_iter(
&memory_allocator, &memory_allocator,
BufferUsage { BufferUsage::STORAGE_BUFFER,
storage_buffer: true,
..BufferUsage::empty()
},
false, false,
(0..12).map(|_| 0u32), (0..12).map(|_| 0u32),
) )

View File

@ -26,6 +26,7 @@ use vulkano::{
}, },
device::{ device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
QueueFlags,
}, },
format::Format, format::Format,
image::{view::ImageView, ImageDimensions, StorageImage}, image::{view::ImageView, ImageDimensions, StorageImage},
@ -65,7 +66,7 @@ fn main() {
.filter_map(|p| { .filter_map(|p| {
p.queue_family_properties() p.queue_family_properties()
.iter() .iter()
.position(|q| q.queue_flags.compute) .position(|q| q.queue_flags.intersects(QueueFlags::COMPUTE))
.map(|i| (p, i as u32)) .map(|i| (p, i as u32))
}) })
.min_by_key(|(p, _)| match p.properties().device_type { .min_by_key(|(p, _)| match p.properties().device_type {
@ -227,10 +228,7 @@ fn main() {
let buf = CpuAccessibleBuffer::from_iter( let buf = CpuAccessibleBuffer::from_iter(
&memory_allocator, &memory_allocator,
BufferUsage { BufferUsage::TRANSFER_DST,
transfer_dst: true,
..BufferUsage::empty()
},
false, false,
(0..1024 * 1024 * 4).map(|_| 0u8), (0..1024 * 1024 * 4).map(|_| 0u8),
) )

View File

@ -26,7 +26,7 @@ mod linux {
}, },
device::{ device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, Queue, physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, Queue,
QueueCreateInfo, QueueCreateInfo, QueueFlags,
}, },
format::Format, format::Format,
image::{view::ImageView, ImageCreateFlags, ImageUsage, StorageImage, SwapchainImage}, image::{view::ImageView, ImageCreateFlags, ImageUsage, StorageImage, SwapchainImage},
@ -107,16 +107,8 @@ mod linux {
array_layers: 1, array_layers: 1,
}, },
Format::R16G16B16A16_UNORM, Format::R16G16B16A16_UNORM,
ImageUsage { ImageUsage::SAMPLED | ImageUsage::TRANSFER_SRC | ImageUsage::TRANSFER_DST,
sampled: true, ImageCreateFlags::MUTABLE_FORMAT,
transfer_src: true,
transfer_dst: true,
..ImageUsage::empty()
},
ImageCreateFlags {
mutable_format: true,
..ImageCreateFlags::empty()
},
[queue.queue_family_index()], [queue.queue_family_index()],
) )
.unwrap(); .unwrap();
@ -132,10 +124,7 @@ mod linux {
Semaphore::new( Semaphore::new(
device.clone(), device.clone(),
SemaphoreCreateInfo { SemaphoreCreateInfo {
export_handle_types: ExternalSemaphoreHandleTypes { export_handle_types: ExternalSemaphoreHandleTypes::OPAQUE_FD,
opaque_fd: true,
..ExternalSemaphoreHandleTypes::empty()
},
..Default::default() ..Default::default()
}, },
) )
@ -145,10 +134,7 @@ mod linux {
Semaphore::new( Semaphore::new(
device.clone(), device.clone(),
SemaphoreCreateInfo { SemaphoreCreateInfo {
export_handle_types: ExternalSemaphoreHandleTypes { export_handle_types: ExternalSemaphoreHandleTypes::OPAQUE_FD,
opaque_fd: true,
..ExternalSemaphoreHandleTypes::empty()
},
..Default::default() ..Default::default()
}, },
) )
@ -486,7 +472,7 @@ mod linux {
.iter() .iter()
.enumerate() .enumerate()
.position(|(i, q)| { .position(|(i, q)| {
q.queue_flags.graphics q.queue_flags.intersects(QueueFlags::GRAPHICS)
&& p.surface_support(i as u32, &surface).unwrap_or(false) && p.surface_support(i as u32, &surface).unwrap_or(false)
}) })
.map(|i| (p, i as u32)) .map(|i| (p, i as u32))
@ -550,13 +536,10 @@ mod linux {
min_image_count: surface_capabilities.min_image_count, min_image_count: surface_capabilities.min_image_count,
image_format, image_format,
image_extent: window.inner_size().into(), image_extent: window.inner_size().into(),
image_usage: ImageUsage { image_usage: ImageUsage::COLOR_ATTACHMENT,
color_attachment: true,
..ImageUsage::empty()
},
composite_alpha: surface_capabilities composite_alpha: surface_capabilities
.supported_composite_alpha .supported_composite_alpha
.iter() .into_iter()
.next() .next()
.unwrap(), .unwrap(),
..Default::default() ..Default::default()
@ -583,10 +566,7 @@ mod linux {
]; ];
let vertex_buffer = CpuAccessibleBuffer::<[Vertex]>::from_iter( let vertex_buffer = CpuAccessibleBuffer::<[Vertex]>::from_iter(
&memory_allocator, &memory_allocator,
BufferUsage { BufferUsage::VERTEX_BUFFER,
vertex_buffer: true,
..BufferUsage::empty()
},
false, false,
vertices, vertices,
) )

View File

@ -22,6 +22,7 @@ use vulkano::{
}, },
device::{ device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
QueueFlags,
}, },
format::Format, format::Format,
image::{ image::{
@ -91,7 +92,8 @@ fn main() {
.iter() .iter()
.enumerate() .enumerate()
.position(|(i, q)| { .position(|(i, q)| {
q.queue_flags.graphics && p.surface_support(i as u32, &surface).unwrap_or(false) q.queue_flags.intersects(QueueFlags::GRAPHICS)
&& p.surface_support(i as u32, &surface).unwrap_or(false)
}) })
.map(|i| (p, i as u32)) .map(|i| (p, i as u32))
}) })
@ -146,13 +148,10 @@ fn main() {
min_image_count: surface_capabilities.min_image_count, min_image_count: surface_capabilities.min_image_count,
image_format, image_format,
image_extent: window.inner_size().into(), image_extent: window.inner_size().into(),
image_usage: ImageUsage { image_usage: ImageUsage::COLOR_ATTACHMENT,
color_attachment: true,
..ImageUsage::empty()
},
composite_alpha: surface_capabilities composite_alpha: surface_capabilities
.supported_composite_alpha .supported_composite_alpha
.iter() .into_iter()
.next() .next()
.unwrap(), .unwrap(),
..Default::default() ..Default::default()
@ -186,10 +185,7 @@ fn main() {
]; ];
let vertex_buffer = CpuAccessibleBuffer::<[Vertex]>::from_iter( let vertex_buffer = CpuAccessibleBuffer::<[Vertex]>::from_iter(
&memory_allocator, &memory_allocator,
BufferUsage { BufferUsage::VERTEX_BUFFER,
vertex_buffer: true,
..BufferUsage::empty()
},
false, false,
vertices, vertices,
) )
@ -250,10 +246,7 @@ fn main() {
let buffer = CpuAccessibleBuffer::from_iter( let buffer = CpuAccessibleBuffer::from_iter(
&memory_allocator, &memory_allocator,
BufferUsage { BufferUsage::TRANSFER_SRC,
transfer_src: true,
..BufferUsage::empty()
},
false, false,
image_data, image_data,
) )

View File

@ -20,6 +20,7 @@ use vulkano::{
}, },
device::{ device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
QueueFlags,
}, },
format::Format, format::Format,
image::{ image::{
@ -89,7 +90,8 @@ fn main() {
.iter() .iter()
.enumerate() .enumerate()
.position(|(i, q)| { .position(|(i, q)| {
q.queue_flags.graphics && p.surface_support(i as u32, &surface).unwrap_or(false) q.queue_flags.intersects(QueueFlags::GRAPHICS)
&& p.surface_support(i as u32, &surface).unwrap_or(false)
}) })
.map(|i| (p, i as u32)) .map(|i| (p, i as u32))
}) })
@ -144,13 +146,10 @@ fn main() {
min_image_count: surface_capabilities.min_image_count, min_image_count: surface_capabilities.min_image_count,
image_format, image_format,
image_extent: window.inner_size().into(), image_extent: window.inner_size().into(),
image_usage: ImageUsage { image_usage: ImageUsage::COLOR_ATTACHMENT,
color_attachment: true,
..ImageUsage::empty()
},
composite_alpha: surface_capabilities composite_alpha: surface_capabilities
.supported_composite_alpha .supported_composite_alpha
.iter() .into_iter()
.next() .next()
.unwrap(), .unwrap(),
..Default::default() ..Default::default()
@ -184,10 +183,7 @@ fn main() {
]; ];
let vertex_buffer = CpuAccessibleBuffer::<[Vertex]>::from_iter( let vertex_buffer = CpuAccessibleBuffer::<[Vertex]>::from_iter(
&memory_allocator, &memory_allocator,
BufferUsage { BufferUsage::VERTEX_BUFFER,
vertex_buffer: true,
..BufferUsage::empty()
},
false, false,
vertices, vertices,
) )

View File

@ -29,6 +29,7 @@ use vulkano::{
}, },
device::{ device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
QueueFlags,
}, },
format::Format, format::Format,
image::{ image::{
@ -95,7 +96,8 @@ fn main() {
.iter() .iter()
.enumerate() .enumerate()
.position(|(i, q)| { .position(|(i, q)| {
q.queue_flags.graphics && p.surface_support(i as u32, &surface).unwrap_or(false) q.queue_flags.intersects(QueueFlags::GRAPHICS)
&& p.surface_support(i as u32, &surface).unwrap_or(false)
}) })
.map(|i| (p, i as u32)) .map(|i| (p, i as u32))
}) })
@ -150,13 +152,10 @@ fn main() {
min_image_count: surface_capabilities.min_image_count, min_image_count: surface_capabilities.min_image_count,
image_format, image_format,
image_extent: window.inner_size().into(), image_extent: window.inner_size().into(),
image_usage: ImageUsage { image_usage: ImageUsage::COLOR_ATTACHMENT,
color_attachment: true,
..ImageUsage::empty()
},
composite_alpha: surface_capabilities composite_alpha: surface_capabilities
.supported_composite_alpha .supported_composite_alpha
.iter() .into_iter()
.next() .next()
.unwrap(), .unwrap(),
..Default::default() ..Default::default()
@ -190,10 +189,7 @@ fn main() {
]; ];
let vertex_buffer = CpuAccessibleBuffer::<[Vertex]>::from_iter( let vertex_buffer = CpuAccessibleBuffer::<[Vertex]>::from_iter(
&memory_allocator, &memory_allocator,
BufferUsage { BufferUsage::VERTEX_BUFFER,
vertex_buffer: true,
..BufferUsage::empty()
},
false, false,
vertices, vertices,
) )

View File

@ -37,6 +37,7 @@ use vulkano::{
}, },
device::{ device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
QueueFlags,
}, },
image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage}, image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage},
impl_vertex, impl_vertex,
@ -108,7 +109,8 @@ fn main() {
.iter() .iter()
.enumerate() .enumerate()
.position(|(i, q)| { .position(|(i, q)| {
q.queue_flags.graphics && p.surface_support(i as u32, &surface).unwrap_or(false) q.queue_flags.intersects(QueueFlags::GRAPHICS)
&& p.surface_support(i as u32, &surface).unwrap_or(false)
}) })
.map(|i| (p, i as u32)) .map(|i| (p, i as u32))
}) })
@ -164,13 +166,10 @@ fn main() {
min_image_count: surface_capabilities.min_image_count, min_image_count: surface_capabilities.min_image_count,
image_format, image_format,
image_extent: window.inner_size().into(), image_extent: window.inner_size().into(),
image_usage: ImageUsage { image_usage: ImageUsage::COLOR_ATTACHMENT,
color_attachment: true,
..ImageUsage::empty()
},
composite_alpha: surface_capabilities composite_alpha: surface_capabilities
.supported_composite_alpha .supported_composite_alpha
.iter() .into_iter()
.next() .next()
.unwrap(), .unwrap(),
..Default::default() ..Default::default()
@ -261,20 +260,12 @@ fn main() {
// set the number of vertices to draw // set the number of vertices to draw
let indirect_args_pool: CpuBufferPool<DrawIndirectCommand> = CpuBufferPool::new( let indirect_args_pool: CpuBufferPool<DrawIndirectCommand> = CpuBufferPool::new(
memory_allocator.clone(), memory_allocator.clone(),
BufferUsage { BufferUsage::INDIRECT_BUFFER | BufferUsage::STORAGE_BUFFER,
indirect_buffer: true,
storage_buffer: true,
..BufferUsage::empty()
},
MemoryUsage::Upload, MemoryUsage::Upload,
); );
let vertex_pool: CpuBufferPool<Vertex> = CpuBufferPool::new( let vertex_pool: CpuBufferPool<Vertex> = CpuBufferPool::new(
memory_allocator, memory_allocator,
BufferUsage { BufferUsage::STORAGE_BUFFER | BufferUsage::VERTEX_BUFFER,
storage_buffer: true,
vertex_buffer: true,
..BufferUsage::empty()
},
MemoryUsage::Upload, MemoryUsage::Upload,
); );

View File

@ -22,6 +22,7 @@ use vulkano::{
}, },
device::{ device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
QueueFlags,
}, },
image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage}, image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage},
impl_vertex, impl_vertex,
@ -105,7 +106,8 @@ fn main() {
.iter() .iter()
.enumerate() .enumerate()
.position(|(i, q)| { .position(|(i, q)| {
q.queue_flags.graphics && p.surface_support(i as u32, &surface).unwrap_or(false) q.queue_flags.intersects(QueueFlags::GRAPHICS)
&& p.surface_support(i as u32, &surface).unwrap_or(false)
}) })
.map(|i| (p, i as u32)) .map(|i| (p, i as u32))
}) })
@ -161,13 +163,10 @@ fn main() {
min_image_count: surface_capabilities.min_image_count, min_image_count: surface_capabilities.min_image_count,
image_format, image_format,
image_extent: window.inner_size().into(), image_extent: window.inner_size().into(),
image_usage: ImageUsage { image_usage: ImageUsage::COLOR_ATTACHMENT,
color_attachment: true,
..ImageUsage::empty()
},
composite_alpha: surface_capabilities composite_alpha: surface_capabilities
.supported_composite_alpha .supported_composite_alpha
.iter() .into_iter()
.next() .next()
.unwrap(), .unwrap(),
..Default::default() ..Default::default()
@ -194,10 +193,7 @@ fn main() {
let vertex_buffer = { let vertex_buffer = {
CpuAccessibleBuffer::from_iter( CpuAccessibleBuffer::from_iter(
&memory_allocator, &memory_allocator,
BufferUsage { BufferUsage::VERTEX_BUFFER,
vertex_buffer: true,
..BufferUsage::empty()
},
false, false,
vertices, vertices,
) )
@ -229,10 +225,7 @@ fn main() {
}; };
let instance_buffer = CpuAccessibleBuffer::from_iter( let instance_buffer = CpuAccessibleBuffer::from_iter(
&memory_allocator, &memory_allocator,
BufferUsage { BufferUsage::VERTEX_BUFFER,
vertex_buffer: true,
..BufferUsage::empty()
},
false, false,
instances, instances,
) )

View File

@ -57,10 +57,7 @@ impl FractalComputePipeline {
let palette_size = colors.len() as i32; let palette_size = colors.len() as i32;
let palette = CpuAccessibleBuffer::from_iter( let palette = CpuAccessibleBuffer::from_iter(
&memory_allocator, &memory_allocator,
BufferUsage { BufferUsage::STORAGE_BUFFER,
storage_buffer: true,
..BufferUsage::empty()
},
false, false,
colors, colors,
) )
@ -103,10 +100,7 @@ impl FractalComputePipeline {
} }
self.palette = CpuAccessibleBuffer::from_iter( self.palette = CpuAccessibleBuffer::from_iter(
&self.memory_allocator, &self.memory_allocator,
BufferUsage { BufferUsage::STORAGE_BUFFER,
storage_buffer: true,
..BufferUsage::empty()
},
false, false,
colors.into_iter(), colors.into_iter(),
) )

View File

@ -57,13 +57,10 @@ fn main() {
primary_window_renderer.add_additional_image_view( primary_window_renderer.add_additional_image_view(
render_target_id, render_target_id,
DEFAULT_IMAGE_FORMAT, DEFAULT_IMAGE_FORMAT,
ImageUsage { ImageUsage::SAMPLED
sampled: true, | ImageUsage::STORAGE
storage: true, | ImageUsage::COLOR_ATTACHMENT
color_attachment: true, | ImageUsage::TRANSFER_DST,
transfer_dst: true,
..ImageUsage::empty()
},
); );
// Create app to hold the logic of our fractal explorer // Create app to hold the logic of our fractal explorer

View File

@ -89,20 +89,14 @@ impl PixelsDrawPipeline {
let (vertices, indices) = textured_quad(2.0, 2.0); let (vertices, indices) = textured_quad(2.0, 2.0);
let vertex_buffer = CpuAccessibleBuffer::<[TexturedVertex]>::from_iter( let vertex_buffer = CpuAccessibleBuffer::<[TexturedVertex]>::from_iter(
memory_allocator, memory_allocator,
BufferUsage { BufferUsage::VERTEX_BUFFER,
vertex_buffer: true,
..BufferUsage::empty()
},
false, false,
vertices, vertices,
) )
.unwrap(); .unwrap();
let index_buffer = CpuAccessibleBuffer::<[u32]>::from_iter( let index_buffer = CpuAccessibleBuffer::<[u32]>::from_iter(
memory_allocator, memory_allocator,
BufferUsage { BufferUsage::INDEX_BUFFER,
index_buffer: true,
..BufferUsage::empty()
},
false, false,
indices, indices,
) )

View File

@ -74,6 +74,7 @@ use vulkano::{
}, },
device::{ device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
QueueFlags,
}, },
format::Format, format::Format,
image::{view::ImageView, AttachmentImage, ImageDimensions, SampleCount, StorageImage}, image::{view::ImageView, AttachmentImage, ImageDimensions, SampleCount, StorageImage},
@ -119,7 +120,7 @@ fn main() {
.filter_map(|p| { .filter_map(|p| {
p.queue_family_properties() p.queue_family_properties()
.iter() .iter()
.position(|q| q.queue_flags.graphics) .position(|q| q.queue_flags.intersects(QueueFlags::GRAPHICS))
.map(|i| (p, i as u32)) .map(|i| (p, i as u32))
}) })
.min_by_key(|(p, _)| match p.properties().device_type { .min_by_key(|(p, _)| match p.properties().device_type {
@ -288,10 +289,7 @@ fn main() {
]; ];
let vertex_buffer = CpuAccessibleBuffer::from_iter( let vertex_buffer = CpuAccessibleBuffer::from_iter(
&memory_allocator, &memory_allocator,
BufferUsage { BufferUsage::VERTEX_BUFFER,
vertex_buffer: true,
..BufferUsage::empty()
},
false, false,
vertices, vertices,
) )
@ -321,10 +319,7 @@ fn main() {
let buf = CpuAccessibleBuffer::from_iter( let buf = CpuAccessibleBuffer::from_iter(
&memory_allocator, &memory_allocator,
BufferUsage { BufferUsage::TRANSFER_DST,
transfer_dst: true,
..BufferUsage::empty()
},
false, false,
(0..1024 * 1024 * 4).map(|_| 0u8), (0..1024 * 1024 * 4).map(|_| 0u8),
) )

View File

@ -26,6 +26,7 @@ use vulkano::{
}, },
device::{ device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
QueueFlags,
}, },
image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage}, image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage},
impl_vertex, impl_vertex,
@ -105,7 +106,7 @@ fn main() {
.iter() .iter()
.enumerate() .enumerate()
.position(|(i, q)| { .position(|(i, q)| {
q.queue_flags.graphics q.queue_flags.intersects(QueueFlags::GRAPHICS)
&& p.surface_support(i as u32, &surface).unwrap_or(false) && p.surface_support(i as u32, &surface).unwrap_or(false)
}) })
.map(|i| (p, i as u32)) .map(|i| (p, i as u32))
@ -166,13 +167,10 @@ fn main() {
min_image_count: surface_caps.min_image_count, min_image_count: surface_caps.min_image_count,
image_format, image_format,
image_extent: window.inner_size().into(), image_extent: window.inner_size().into(),
image_usage: ImageUsage { image_usage: ImageUsage::COLOR_ATTACHMENT,
color_attachment: true,
..ImageUsage::empty()
},
composite_alpha: surface_caps composite_alpha: surface_caps
.supported_composite_alpha .supported_composite_alpha
.iter() .into_iter()
.next() .next()
.unwrap(), .unwrap(),
..Default::default() ..Default::default()
@ -203,10 +201,7 @@ fn main() {
]; ];
let vertex_buffer = CpuAccessibleBuffer::from_iter( let vertex_buffer = CpuAccessibleBuffer::from_iter(
&memory_allocator, &memory_allocator,
BufferUsage { BufferUsage::VERTEX_BUFFER,
vertex_buffer: true,
..BufferUsage::empty()
},
false, false,
vertices, vertices,
) )
@ -329,7 +324,7 @@ fn main() {
let (swapchain, images) = { let (swapchain, images) = {
let composite_alpha = surface_caps let composite_alpha = surface_caps
.supported_composite_alpha .supported_composite_alpha
.iter() .into_iter()
.next() .next()
.unwrap(); .unwrap();
let image_format = Some( let image_format = Some(
@ -347,10 +342,7 @@ fn main() {
min_image_count: surface_caps.min_image_count, min_image_count: surface_caps.min_image_count,
image_format, image_format,
image_extent: window.inner_size().into(), image_extent: window.inner_size().into(),
image_usage: ImageUsage { image_usage: ImageUsage::COLOR_ATTACHMENT,
color_attachment: true,
..ImageUsage::empty()
},
composite_alpha, composite_alpha,
..Default::default() ..Default::default()
}, },

View File

@ -47,10 +47,7 @@ fn rand_grid(
) -> Arc<CpuAccessibleBuffer<[u32]>> { ) -> Arc<CpuAccessibleBuffer<[u32]>> {
CpuAccessibleBuffer::from_iter( CpuAccessibleBuffer::from_iter(
memory_allocator, memory_allocator,
BufferUsage { BufferUsage::STORAGE_BUFFER,
storage_buffer: true,
..BufferUsage::empty()
},
false, false,
(0..(size[0] * size[1])) (0..(size[0] * size[1]))
.map(|_| rand::thread_rng().gen_range(0u32..=1)) .map(|_| rand::thread_rng().gen_range(0u32..=1))
@ -87,13 +84,10 @@ impl GameOfLifeComputePipeline {
compute_queue.clone(), compute_queue.clone(),
size, size,
Format::R8G8B8A8_UNORM, Format::R8G8B8A8_UNORM,
ImageUsage { ImageUsage::SAMPLED
sampled: true, | ImageUsage::STORAGE
storage: true, | ImageUsage::COLOR_ATTACHMENT
color_attachment: true, | ImageUsage::TRANSFER_DST,
transfer_dst: true,
..ImageUsage::empty()
},
) )
.unwrap(); .unwrap();

View File

@ -89,20 +89,14 @@ impl PixelsDrawPipeline {
let (vertices, indices) = textured_quad(2.0, 2.0); let (vertices, indices) = textured_quad(2.0, 2.0);
let vertex_buffer = CpuAccessibleBuffer::<[TexturedVertex]>::from_iter( let vertex_buffer = CpuAccessibleBuffer::<[TexturedVertex]>::from_iter(
memory_allocator, memory_allocator,
BufferUsage { BufferUsage::VERTEX_BUFFER,
vertex_buffer: true,
..BufferUsage::empty()
},
false, false,
vertices.into_iter(), vertices.into_iter(),
) )
.unwrap(); .unwrap();
let index_buffer = CpuAccessibleBuffer::<[u32]>::from_iter( let index_buffer = CpuAccessibleBuffer::<[u32]>::from_iter(
memory_allocator, memory_allocator,
BufferUsage { BufferUsage::INDEX_BUFFER,
index_buffer: true,
..BufferUsage::empty()
},
false, false,
indices.into_iter(), indices.into_iter(),
) )

View File

@ -23,7 +23,7 @@ use vulkano::{
}, },
device::{ device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, Features, physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, Features,
QueueCreateInfo, QueueCreateInfo, QueueFlags,
}, },
format::Format, format::Format,
image::{ image::{
@ -93,7 +93,7 @@ fn main() {
.filter_map(|p| { .filter_map(|p| {
p.queue_family_properties() p.queue_family_properties()
.iter() .iter()
.position(|q| q.queue_flags.graphics) .position(|q| q.queue_flags.intersects(QueueFlags::GRAPHICS))
.map(|i| (p, i as u32)) .map(|i| (p, i as u32))
}) })
.min_by_key(|(p, _)| match p.properties().device_type { .min_by_key(|(p, _)| match p.properties().device_type {
@ -140,11 +140,7 @@ fn main() {
array_layers: 2, array_layers: 2,
}, },
Format::B8G8R8A8_SRGB, Format::B8G8R8A8_SRGB,
ImageUsage { ImageUsage::TRANSFER_SRC | ImageUsage::COLOR_ATTACHMENT,
transfer_src: true,
color_attachment: true,
..ImageUsage::empty()
},
ImageCreateFlags::empty(), ImageCreateFlags::empty(),
Some(queue.queue_family_index()), Some(queue.queue_family_index()),
) )
@ -172,10 +168,7 @@ fn main() {
]; ];
let vertex_buffer = CpuAccessibleBuffer::from_iter( let vertex_buffer = CpuAccessibleBuffer::from_iter(
&memory_allocator, &memory_allocator,
BufferUsage { BufferUsage::VERTEX_BUFFER,
vertex_buffer: true,
..BufferUsage::empty()
},
false, false,
vertices, vertices,
) )
@ -286,10 +279,7 @@ fn main() {
let create_buffer = || { let create_buffer = || {
CpuAccessibleBuffer::from_iter( CpuAccessibleBuffer::from_iter(
&memory_allocator, &memory_allocator,
BufferUsage { BufferUsage::TRANSFER_DST,
transfer_dst: true,
..BufferUsage::empty()
},
false, false,
(0..image.dimensions().width() * image.dimensions().height() * 4).map(|_| 0u8), (0..image.dimensions().width() * image.dimensions().height() * 4).map(|_| 0u8),
) )

View File

@ -21,6 +21,7 @@ use vulkano::{
}, },
device::{ device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
QueueFlags,
}, },
format::Format, format::Format,
image::{view::ImageView, AttachmentImage, ImageAccess, ImageUsage, SwapchainImage}, image::{view::ImageView, AttachmentImage, ImageAccess, ImageUsage, SwapchainImage},
@ -84,7 +85,8 @@ fn main() {
.iter() .iter()
.enumerate() .enumerate()
.position(|(i, q)| { .position(|(i, q)| {
q.queue_flags.graphics && p.surface_support(i as u32, &surface).unwrap_or(false) q.queue_flags.intersects(QueueFlags::GRAPHICS)
&& p.surface_support(i as u32, &surface).unwrap_or(false)
}) })
.map(|i| (p, i as u32)) .map(|i| (p, i as u32))
}) })
@ -139,13 +141,10 @@ fn main() {
min_image_count: surface_capabilities.min_image_count, min_image_count: surface_capabilities.min_image_count,
image_format, image_format,
image_extent: window.inner_size().into(), image_extent: window.inner_size().into(),
image_usage: ImageUsage { image_usage: ImageUsage::COLOR_ATTACHMENT,
color_attachment: true,
..ImageUsage::empty()
},
composite_alpha: surface_capabilities composite_alpha: surface_capabilities
.supported_composite_alpha .supported_composite_alpha
.iter() .into_iter()
.next() .next()
.unwrap(), .unwrap(),
..Default::default() ..Default::default()
@ -212,10 +211,7 @@ fn main() {
]; ];
let vertex_buffer = CpuAccessibleBuffer::from_iter( let vertex_buffer = CpuAccessibleBuffer::from_iter(
&memory_allocator, &memory_allocator,
BufferUsage { BufferUsage::VERTEX_BUFFER,
vertex_buffer: true,
..BufferUsage::empty()
},
false, false,
vertices, vertices,
) )
@ -421,15 +417,13 @@ fn main() {
) )
.unwrap() .unwrap()
// Begin query 0, then draw the red triangle. // Begin query 0, then draw the red triangle.
// Enabling the `precise` bit would give exact numeric results. This needs // Enabling the `QueryControlFlags::PRECISE` flag would give exact numeric
// the `occlusion_query_precise` feature to be enabled on the device. // results. This needs the `occlusion_query_precise` feature to be enabled on
// the device.
.begin_query( .begin_query(
query_pool.clone(), query_pool.clone(),
0, 0,
QueryControlFlags { QueryControlFlags::empty(), // QueryControlFlags::PRECISE
precise: false,
..QueryControlFlags::empty()
},
) )
.unwrap() .unwrap()
.bind_vertex_buffers(0, triangle1.clone()) .bind_vertex_buffers(0, triangle1.clone())
@ -439,14 +433,7 @@ fn main() {
.end_query(query_pool.clone(), 0) .end_query(query_pool.clone(), 0)
.unwrap() .unwrap()
// Begin query 1 for the cyan triangle. // Begin query 1 for the cyan triangle.
.begin_query( .begin_query(query_pool.clone(), 1, QueryControlFlags::empty())
query_pool.clone(),
1,
QueryControlFlags {
precise: false,
..QueryControlFlags::empty()
},
)
.unwrap() .unwrap()
.bind_vertex_buffers(0, triangle2.clone()) .bind_vertex_buffers(0, triangle2.clone())
.draw(triangle2.len() as u32, 1, 0, 0) .draw(triangle2.len() as u32, 1, 0, 0)
@ -454,14 +441,7 @@ fn main() {
.end_query(query_pool.clone(), 1) .end_query(query_pool.clone(), 1)
.unwrap() .unwrap()
// Finally, query 2 for the green triangle. // Finally, query 2 for the green triangle.
.begin_query( .begin_query(query_pool.clone(), 2, QueryControlFlags::empty())
query_pool.clone(),
2,
QueryControlFlags {
precise: false,
..QueryControlFlags::empty()
},
)
.unwrap() .unwrap()
.bind_vertex_buffers(0, triangle3.clone()) .bind_vertex_buffers(0, triangle3.clone())
.draw(triangle3.len() as u32, 1, 0, 0) .draw(triangle3.len() as u32, 1, 0, 0)
@ -505,30 +485,29 @@ fn main() {
// `copy_query_pool_results` function on a command buffer to write results to a // `copy_query_pool_results` function on a command buffer to write results to a
// Vulkano buffer. This could then be used to influence draw operations further down // Vulkano buffer. This could then be used to influence draw operations further down
// the line, either in the same frame or a future frame. // the line, either in the same frame or a future frame.
#[rustfmt::skip]
query_pool query_pool
.queries_range(0..3) .queries_range(0..3)
.unwrap() .unwrap()
.get_results( .get_results(
&mut query_results, &mut query_results,
QueryResultFlags { // Block the function call until the results are available.
// Block the function call until the results are available. // Note: if not all the queries have actually been executed, then this
// Note: if not all the queries have actually been executed, then this // will wait forever for something that never happens!
// will wait forever for something that never happens! QueryResultFlags::WAIT
wait: true,
// Blocking and waiting will never give partial results. // Enable this flag to give partial results if available, instead of waiting
partial: false, // for the full results.
// | QueryResultFlags::PARTIAL
// Blocking and waiting will ensure the results are always available after // Blocking and waiting will ensure the results are always available after
// the function returns. // the function returns.
// //
// If you disable waiting, then this can be used to include the // If you disable waiting, then this flag can be enabled to include the
// availability of each query's results. You need one extra element per // availability of each query's results. You need one extra element per
// query in your `query_results` buffer for this. This element will // query in your `query_results` buffer for this. This element will
// be filled with a zero/nonzero value indicating availability. // be filled with a zero/nonzero value indicating availability.
with_availability: false, // | QueryResultFlags::WITH_AVAILABILITY
..QueryResultFlags::empty()
},
) )
.unwrap(); .unwrap();
@ -564,11 +543,7 @@ fn window_size_dependent_setup(
memory_allocator, memory_allocator,
dimensions, dimensions,
Format::D16_UNORM, Format::D16_UNORM,
ImageUsage { ImageUsage::DEPTH_STENCIL_ATTACHMENT | ImageUsage::TRANSIENT_ATTACHMENT,
depth_stencil_attachment: true,
transient_attachment: true,
..ImageUsage::empty()
},
) )
.unwrap(), .unwrap(),
) )

View File

@ -34,6 +34,7 @@ use std::{
use vulkano::{ use vulkano::{
device::{ device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
QueueFlags,
}, },
instance::{Instance, InstanceCreateInfo}, instance::{Instance, InstanceCreateInfo},
pipeline::{cache::PipelineCache, ComputePipeline}, pipeline::{cache::PipelineCache, ComputePipeline},
@ -65,7 +66,7 @@ fn main() {
.filter_map(|p| { .filter_map(|p| {
p.queue_family_properties() p.queue_family_properties()
.iter() .iter()
.position(|q| q.queue_flags.compute) .position(|q| q.queue_flags.intersects(QueueFlags::COMPUTE))
.map(|i| (p, i as u32)) .map(|i| (p, i as u32))
}) })
.min_by_key(|(p, _)| match p.properties().device_type { .min_by_key(|(p, _)| match p.properties().device_type {

View File

@ -22,6 +22,7 @@ use vulkano::{
}, },
device::{ device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
QueueFlags,
}, },
instance::{Instance, InstanceCreateInfo}, instance::{Instance, InstanceCreateInfo},
memory::allocator::StandardMemoryAllocator, memory::allocator::StandardMemoryAllocator,
@ -53,7 +54,7 @@ fn main() {
.filter_map(|p| { .filter_map(|p| {
p.queue_family_properties() p.queue_family_properties()
.iter() .iter()
.position(|q| q.queue_flags.compute) .position(|q| q.queue_flags.intersects(QueueFlags::COMPUTE))
.map(|i| (p, i as u32)) .map(|i| (p, i as u32))
}) })
.min_by_key(|(p, _)| match p.properties().device_type { .min_by_key(|(p, _)| match p.properties().device_type {
@ -139,10 +140,7 @@ fn main() {
let data_iter = 0..65536u32; let data_iter = 0..65536u32;
CpuAccessibleBuffer::from_iter( CpuAccessibleBuffer::from_iter(
&memory_allocator, &memory_allocator,
BufferUsage { BufferUsage::STORAGE_BUFFER,
storage_buffer: true,
..BufferUsage::empty()
},
false, false,
data_iter, data_iter,
) )

View File

@ -18,6 +18,7 @@ use vulkano::{
descriptor_set::WriteDescriptorSet, descriptor_set::WriteDescriptorSet,
device::{ device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
QueueFlags,
}, },
format::Format, format::Format,
image::{ image::{
@ -85,7 +86,8 @@ fn main() {
.iter() .iter()
.enumerate() .enumerate()
.position(|(i, q)| { .position(|(i, q)| {
q.queue_flags.graphics && p.surface_support(i as u32, &surface).unwrap_or(false) q.queue_flags.intersects(QueueFlags::GRAPHICS)
&& p.surface_support(i as u32, &surface).unwrap_or(false)
}) })
.map(|i| (p, i as u32)) .map(|i| (p, i as u32))
}) })
@ -140,13 +142,10 @@ fn main() {
min_image_count: surface_capabilities.min_image_count, min_image_count: surface_capabilities.min_image_count,
image_format, image_format,
image_extent: window.inner_size().into(), image_extent: window.inner_size().into(),
image_usage: ImageUsage { image_usage: ImageUsage::COLOR_ATTACHMENT,
color_attachment: true,
..ImageUsage::empty()
},
composite_alpha: surface_capabilities composite_alpha: surface_capabilities
.supported_composite_alpha .supported_composite_alpha
.iter() .into_iter()
.next() .next()
.unwrap(), .unwrap(),
..Default::default() ..Default::default()
@ -180,10 +179,7 @@ fn main() {
]; ];
let vertex_buffer = CpuAccessibleBuffer::<[Vertex]>::from_iter( let vertex_buffer = CpuAccessibleBuffer::<[Vertex]>::from_iter(
&memory_allocator, &memory_allocator,
BufferUsage { BufferUsage::VERTEX_BUFFER,
vertex_buffer: true,
..BufferUsage::empty()
},
false, false,
vertices, vertices,
) )

View File

@ -29,6 +29,7 @@ use vulkano::{
}, },
device::{ device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
QueueFlags,
}, },
image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage}, image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage},
impl_vertex, impl_vertex,
@ -100,7 +101,8 @@ fn main() {
.iter() .iter()
.enumerate() .enumerate()
.position(|(i, q)| { .position(|(i, q)| {
q.queue_flags.graphics && p.surface_support(i as u32, &surface).unwrap_or(false) q.queue_flags.intersects(QueueFlags::GRAPHICS)
&& p.surface_support(i as u32, &surface).unwrap_or(false)
}) })
.map(|i| (p, i as u32)) .map(|i| (p, i as u32))
}) })
@ -155,13 +157,10 @@ fn main() {
min_image_count: surface_capabilities.min_image_count, min_image_count: surface_capabilities.min_image_count,
image_format, image_format,
image_extent: window.inner_size().into(), image_extent: window.inner_size().into(),
image_usage: ImageUsage { image_usage: ImageUsage::COLOR_ATTACHMENT,
color_attachment: true,
..ImageUsage::empty()
},
composite_alpha: surface_capabilities composite_alpha: surface_capabilities
.supported_composite_alpha .supported_composite_alpha
.iter() .into_iter()
.next() .next()
.unwrap(), .unwrap(),
..Default::default() ..Default::default()
@ -240,10 +239,7 @@ fn main() {
]; ];
let vertex_buffer = CpuAccessibleBuffer::from_iter( let vertex_buffer = CpuAccessibleBuffer::from_iter(
&memory_allocator, &memory_allocator,
BufferUsage { BufferUsage::VERTEX_BUFFER,
vertex_buffer: true,
..BufferUsage::empty()
},
false, false,
vertices, vertices,
) )

View File

@ -24,7 +24,7 @@ use vulkano::{
}, },
device::{ device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, Features, physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, Features,
QueueCreateInfo, QueueCreateInfo, QueueFlags,
}, },
format::Format, format::Format,
image::{ image::{
@ -94,7 +94,8 @@ fn main() {
.iter() .iter()
.enumerate() .enumerate()
.position(|(i, q)| { .position(|(i, q)| {
q.queue_flags.graphics && p.surface_support(i as u32, &surface).unwrap_or(false) q.queue_flags.intersects(QueueFlags::GRAPHICS)
&& p.surface_support(i as u32, &surface).unwrap_or(false)
}) })
.map(|i| (p, i as u32)) .map(|i| (p, i as u32))
}) })
@ -156,13 +157,10 @@ fn main() {
min_image_count: surface_capabilities.min_image_count, min_image_count: surface_capabilities.min_image_count,
image_format, image_format,
image_extent: window.inner_size().into(), image_extent: window.inner_size().into(),
image_usage: ImageUsage { image_usage: ImageUsage::COLOR_ATTACHMENT,
color_attachment: true,
..ImageUsage::empty()
},
composite_alpha: surface_capabilities composite_alpha: surface_capabilities
.supported_composite_alpha .supported_composite_alpha
.iter() .into_iter()
.next() .next()
.unwrap(), .unwrap(),
..Default::default() ..Default::default()
@ -246,10 +244,7 @@ fn main() {
]; ];
let vertex_buffer = CpuAccessibleBuffer::<[Vertex]>::from_iter( let vertex_buffer = CpuAccessibleBuffer::<[Vertex]>::from_iter(
&memory_allocator, &memory_allocator,
BufferUsage { BufferUsage::VERTEX_BUFFER,
vertex_buffer: true,
..BufferUsage::empty()
},
false, false,
vertices, vertices,
) )

View File

@ -21,6 +21,7 @@ use vulkano::{
}, },
device::{ device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
QueueFlags,
}, },
instance::{Instance, InstanceCreateInfo}, instance::{Instance, InstanceCreateInfo},
memory::allocator::StandardMemoryAllocator, memory::allocator::StandardMemoryAllocator,
@ -52,7 +53,7 @@ fn main() {
.filter_map(|p| { .filter_map(|p| {
p.queue_family_properties() p.queue_family_properties()
.iter() .iter()
.position(|q| q.queue_flags.compute) .position(|q| q.queue_flags.intersects(QueueFlags::COMPUTE))
.map(|i| (p, i as u32)) .map(|i| (p, i as u32))
}) })
.min_by_key(|(p, _)| match p.properties().device_type { .min_by_key(|(p, _)| match p.properties().device_type {
@ -127,12 +128,7 @@ fn main() {
let data_iter = (0..65536u32).map(|n| if n < 65536 / 2 { n } else { 0 }); let data_iter = (0..65536u32).map(|n| if n < 65536 / 2 { n } else { 0 });
CpuAccessibleBuffer::from_iter( CpuAccessibleBuffer::from_iter(
&memory_allocator, &memory_allocator,
BufferUsage { BufferUsage::STORAGE_BUFFER | BufferUsage::TRANSFER_SRC | BufferUsage::TRANSFER_DST,
storage_buffer: true,
transfer_src: true,
transfer_dst: true,
..BufferUsage::empty()
},
false, false,
data_iter, data_iter,
) )

View File

@ -21,6 +21,7 @@ use vulkano::{
}, },
device::{ device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
QueueFlags,
}, },
instance::{Instance, InstanceCreateInfo}, instance::{Instance, InstanceCreateInfo},
memory::allocator::StandardMemoryAllocator, memory::allocator::StandardMemoryAllocator,
@ -52,7 +53,7 @@ fn main() {
.filter_map(|p| { .filter_map(|p| {
p.queue_family_properties() p.queue_family_properties()
.iter() .iter()
.position(|q| q.queue_flags.compute) .position(|q| q.queue_flags.intersects(QueueFlags::COMPUTE))
.map(|i| (p, i as u32)) .map(|i| (p, i as u32))
}) })
.min_by_key(|(p, _)| match p.properties().device_type { .min_by_key(|(p, _)| match p.properties().device_type {
@ -134,10 +135,7 @@ fn main() {
let data_iter = 0..65536u32; let data_iter = 0..65536u32;
CpuAccessibleBuffer::from_iter( CpuAccessibleBuffer::from_iter(
&memory_allocator, &memory_allocator,
BufferUsage { BufferUsage::STORAGE_BUFFER,
storage_buffer: true,
..BufferUsage::empty()
},
false, false,
data_iter, data_iter,
) )

View File

@ -38,7 +38,7 @@ use vulkano::{
}, },
device::{ device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, Queue, physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, Queue,
QueueCreateInfo, QueueCreateInfo, QueueFlags,
}, },
instance::{Instance, InstanceCreateInfo}, instance::{Instance, InstanceCreateInfo},
memory::allocator::StandardMemoryAllocator, memory::allocator::StandardMemoryAllocator,
@ -70,7 +70,7 @@ fn main() {
.filter_map(|p| { .filter_map(|p| {
p.queue_family_properties() p.queue_family_properties()
.iter() .iter()
.position(|q| q.queue_flags.compute) .position(|q| q.queue_flags.intersects(QueueFlags::COMPUTE))
.map(|i| (p, i as u32)) .map(|i| (p, i as u32))
}) })
.min_by_key(|(p, _)| match p.properties().device_type { .min_by_key(|(p, _)| match p.properties().device_type {
@ -248,10 +248,7 @@ fn main() {
let data_iter = 0..65536u32; let data_iter = 0..65536u32;
CpuAccessibleBuffer::from_iter( CpuAccessibleBuffer::from_iter(
&memory_allocator, &memory_allocator,
BufferUsage { BufferUsage::STORAGE_BUFFER,
storage_buffer: true,
..BufferUsage::empty()
},
false, false,
data_iter, data_iter,
) )

View File

@ -26,6 +26,7 @@ use vulkano::{
}, },
device::{ device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
QueueFlags,
}, },
image::{view::ImageView, ImageUsage}, image::{view::ImageView, ImageUsage},
impl_vertex, impl_vertex,
@ -93,7 +94,8 @@ fn main() {
.iter() .iter()
.enumerate() .enumerate()
.position(|(i, q)| { .position(|(i, q)| {
q.queue_flags.graphics && p.surface_support(i as u32, &surface).unwrap_or(false) q.queue_flags.intersects(QueueFlags::GRAPHICS)
&& p.surface_support(i as u32, &surface).unwrap_or(false)
}) })
.map(|i| (p, i as u32)) .map(|i| (p, i as u32))
}) })
@ -147,13 +149,10 @@ fn main() {
min_image_count: surface_capabilities.min_image_count, min_image_count: surface_capabilities.min_image_count,
image_format, image_format,
image_extent: [WINDOW_WIDTH as u32, WINDOW_HEIGHT as u32], image_extent: [WINDOW_WIDTH as u32, WINDOW_HEIGHT as u32],
image_usage: ImageUsage { image_usage: ImageUsage::COLOR_ATTACHMENT,
color_attachment: true,
..ImageUsage::empty()
},
composite_alpha: surface_capabilities composite_alpha: surface_capabilities
.supported_composite_alpha .supported_composite_alpha
.iter() .into_iter()
.next() .next()
.unwrap(), .unwrap(),
present_mode: PresentMode::Fifo, present_mode: PresentMode::Fifo,
@ -345,10 +344,7 @@ fn main() {
// Create a CPU accessible buffer initialized with the vertex data. // Create a CPU accessible buffer initialized with the vertex data.
let temporary_accessible_buffer = CpuAccessibleBuffer::from_iter( let temporary_accessible_buffer = CpuAccessibleBuffer::from_iter(
&memory_allocator, &memory_allocator,
BufferUsage { BufferUsage::TRANSFER_SRC, // Specify this buffer will be used as a transfer source.
transfer_src: true,
..BufferUsage::empty()
}, // Specify this buffer will be used as a transfer source.
false, false,
vertices, vertices,
) )
@ -358,14 +354,7 @@ fn main() {
let device_local_buffer = DeviceLocalBuffer::<[Vertex]>::array( let device_local_buffer = DeviceLocalBuffer::<[Vertex]>::array(
&memory_allocator, &memory_allocator,
PARTICLE_COUNT as vulkano::DeviceSize, PARTICLE_COUNT as vulkano::DeviceSize,
BufferUsage { BufferUsage::STORAGE_BUFFER | BufferUsage::TRANSFER_DST | BufferUsage::VERTEX_BUFFER, // Specify use as a storage buffer, vertex buffer, and transfer destination.
storage_buffer: true,
..BufferUsage::empty()
} | BufferUsage {
transfer_dst: true,
vertex_buffer: true,
..BufferUsage::empty()
}, // Specify use as a storage buffer, vertex buffer, and transfer destination.
device.active_queue_family_indices().iter().copied(), device.active_queue_family_indices().iter().copied(),
) )
.unwrap(); .unwrap();

View File

@ -19,6 +19,7 @@ use vulkano::{
}, },
device::{ device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
QueueFlags,
}, },
instance::{Instance, InstanceCreateInfo}, instance::{Instance, InstanceCreateInfo},
memory::allocator::StandardMemoryAllocator, memory::allocator::StandardMemoryAllocator,
@ -50,7 +51,7 @@ fn main() {
.filter_map(|p| { .filter_map(|p| {
p.queue_family_properties() p.queue_family_properties()
.iter() .iter()
.position(|q| q.queue_flags.compute) .position(|q| q.queue_flags.intersects(QueueFlags::COMPUTE))
.map(|i| (p, i as u32)) .map(|i| (p, i as u32))
}) })
.min_by_key(|(p, _)| match p.properties().device_type { .min_by_key(|(p, _)| match p.properties().device_type {
@ -135,10 +136,7 @@ fn main() {
let data_iter = 0..65536u32; let data_iter = 0..65536u32;
CpuAccessibleBuffer::from_iter( CpuAccessibleBuffer::from_iter(
&memory_allocator, &memory_allocator,
BufferUsage { BufferUsage::STORAGE_BUFFER,
storage_buffer: true,
..BufferUsage::empty()
},
false, false,
data_iter, data_iter,
) )

View File

@ -21,7 +21,7 @@ use vulkano::{
}, },
device::{ device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, DeviceOwned, physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, DeviceOwned,
QueueCreateInfo, QueueCreateInfo, QueueFlags,
}, },
format::Format, format::Format,
image::{view::ImageView, AttachmentImage, ImageAccess, ImageUsage, SwapchainImage}, image::{view::ImageView, AttachmentImage, ImageAccess, ImageUsage, SwapchainImage},
@ -87,7 +87,8 @@ fn main() {
.iter() .iter()
.enumerate() .enumerate()
.position(|(i, q)| { .position(|(i, q)| {
q.queue_flags.graphics && p.surface_support(i as u32, &surface).unwrap_or(false) q.queue_flags.intersects(QueueFlags::GRAPHICS)
&& p.surface_support(i as u32, &surface).unwrap_or(false)
}) })
.map(|i| (p, i as u32)) .map(|i| (p, i as u32))
}) })
@ -143,13 +144,10 @@ fn main() {
min_image_count: surface_capabilities.min_image_count, min_image_count: surface_capabilities.min_image_count,
image_format, image_format,
image_extent: window.inner_size().into(), image_extent: window.inner_size().into(),
image_usage: ImageUsage { image_usage: ImageUsage::COLOR_ATTACHMENT,
color_attachment: true,
..ImageUsage::empty()
},
composite_alpha: surface_capabilities composite_alpha: surface_capabilities
.supported_composite_alpha .supported_composite_alpha
.iter() .into_iter()
.next() .next()
.unwrap(), .unwrap(),
..Default::default() ..Default::default()
@ -162,30 +160,21 @@ fn main() {
let vertex_buffer = CpuAccessibleBuffer::from_iter( let vertex_buffer = CpuAccessibleBuffer::from_iter(
&memory_allocator, &memory_allocator,
BufferUsage { BufferUsage::VERTEX_BUFFER,
vertex_buffer: true,
..BufferUsage::empty()
},
false, false,
VERTICES, VERTICES,
) )
.unwrap(); .unwrap();
let normals_buffer = CpuAccessibleBuffer::from_iter( let normals_buffer = CpuAccessibleBuffer::from_iter(
&memory_allocator, &memory_allocator,
BufferUsage { BufferUsage::VERTEX_BUFFER,
vertex_buffer: true,
..BufferUsage::empty()
},
false, false,
NORMALS, NORMALS,
) )
.unwrap(); .unwrap();
let index_buffer = CpuAccessibleBuffer::from_iter( let index_buffer = CpuAccessibleBuffer::from_iter(
&memory_allocator, &memory_allocator,
BufferUsage { BufferUsage::INDEX_BUFFER,
index_buffer: true,
..BufferUsage::empty()
},
false, false,
INDICES, INDICES,
) )
@ -193,10 +182,7 @@ fn main() {
let uniform_buffer = CpuBufferPool::<vs::ty::Data>::new( let uniform_buffer = CpuBufferPool::<vs::ty::Data>::new(
memory_allocator.clone(), memory_allocator.clone(),
BufferUsage { BufferUsage::UNIFORM_BUFFER,
uniform_buffer: true,
..BufferUsage::empty()
},
MemoryUsage::Upload, MemoryUsage::Upload,
); );

View File

@ -28,7 +28,7 @@ use vulkano::{
}, },
device::{ device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, Features, physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, Features,
QueueCreateInfo, QueueCreateInfo, QueueFlags,
}, },
image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage}, image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage},
impl_vertex, impl_vertex,
@ -192,7 +192,8 @@ fn main() {
.iter() .iter()
.enumerate() .enumerate()
.position(|(i, q)| { .position(|(i, q)| {
q.queue_flags.graphics && p.surface_support(i as u32, &surface).unwrap_or(false) q.queue_flags.intersects(QueueFlags::GRAPHICS)
&& p.surface_support(i as u32, &surface).unwrap_or(false)
}) })
.map(|i| (p, i as u32)) .map(|i| (p, i as u32))
}) })
@ -248,13 +249,10 @@ fn main() {
min_image_count: surface_capabilities.min_image_count, min_image_count: surface_capabilities.min_image_count,
image_format, image_format,
image_extent: window.inner_size().into(), image_extent: window.inner_size().into(),
image_usage: ImageUsage { image_usage: ImageUsage::COLOR_ATTACHMENT,
color_attachment: true,
..ImageUsage::empty()
},
composite_alpha: surface_capabilities composite_alpha: surface_capabilities
.supported_composite_alpha .supported_composite_alpha
.iter() .into_iter()
.next() .next()
.unwrap(), .unwrap(),
..Default::default() ..Default::default()
@ -303,10 +301,7 @@ fn main() {
]; ];
let vertex_buffer = CpuAccessibleBuffer::from_iter( let vertex_buffer = CpuAccessibleBuffer::from_iter(
&memory_allocator, &memory_allocator,
BufferUsage { BufferUsage::VERTEX_BUFFER,
vertex_buffer: true,
..BufferUsage::empty()
},
false, false,
vertices, vertices,
) )

View File

@ -20,6 +20,7 @@ use vulkano::{
}, },
device::{ device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
QueueFlags,
}, },
format::Format, format::Format,
image::{ image::{
@ -91,7 +92,8 @@ fn main() {
.iter() .iter()
.enumerate() .enumerate()
.position(|(i, q)| { .position(|(i, q)| {
q.queue_flags.graphics && p.surface_support(i as u32, &surface).unwrap_or(false) q.queue_flags.intersects(QueueFlags::GRAPHICS)
&& p.surface_support(i as u32, &surface).unwrap_or(false)
}) })
.map(|i| (p, i as u32)) .map(|i| (p, i as u32))
}) })
@ -146,13 +148,10 @@ fn main() {
min_image_count: surface_capabilities.min_image_count, min_image_count: surface_capabilities.min_image_count,
image_format, image_format,
image_extent: window.inner_size().into(), image_extent: window.inner_size().into(),
image_usage: ImageUsage { image_usage: ImageUsage::COLOR_ATTACHMENT,
color_attachment: true,
..ImageUsage::empty()
},
composite_alpha: surface_capabilities composite_alpha: surface_capabilities
.supported_composite_alpha .supported_composite_alpha
.iter() .into_iter()
.next() .next()
.unwrap(), .unwrap(),
..Default::default() ..Default::default()
@ -186,10 +185,7 @@ fn main() {
]; ];
let vertex_buffer = CpuAccessibleBuffer::<[Vertex]>::from_iter( let vertex_buffer = CpuAccessibleBuffer::<[Vertex]>::from_iter(
&memory_allocator, &memory_allocator,
BufferUsage { BufferUsage::VERTEX_BUFFER,
vertex_buffer: true,
..BufferUsage::empty()
},
false, false,
vertices, vertices,
) )

View File

@ -31,7 +31,7 @@ use vulkano::{
}, },
device::{ device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, Features, physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, Features,
QueueCreateInfo, QueueCreateInfo, QueueFlags,
}, },
image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage}, image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage},
impl_vertex, impl_vertex,
@ -142,7 +142,8 @@ fn main() {
// We select a queue family that supports graphics operations. When drawing to // We select a queue family that supports graphics operations. When drawing to
// a window surface, as we do in this example, we also need to check that queues // a window surface, as we do in this example, we also need to check that queues
// in this queue family are capable of presenting images to the surface. // in this queue family are capable of presenting images to the surface.
q.queue_flags.graphics && p.surface_support(i as u32, &surface).unwrap_or(false) q.queue_flags.intersects(QueueFlags::GRAPHICS)
&& p.surface_support(i as u32, &surface).unwrap_or(false)
}) })
// The code here searches for the first queue family that is suitable. If none is // The code here searches for the first queue family that is suitable. If none is
// found, `None` is returned to `filter_map`, which disqualifies this physical // found, `None` is returned to `filter_map`, which disqualifies this physical
@ -261,16 +262,13 @@ fn main() {
// use that. // use that.
image_extent: window.inner_size().into(), image_extent: window.inner_size().into(),
image_usage: ImageUsage { image_usage: ImageUsage::COLOR_ATTACHMENT,
color_attachment: true,
..ImageUsage::empty()
},
// The alpha mode indicates how the alpha value of the final image will behave. For // The alpha mode indicates how the alpha value of the final image will behave. For
// example, you can choose whether the window will be opaque or transparent. // example, you can choose whether the window will be opaque or transparent.
composite_alpha: surface_capabilities composite_alpha: surface_capabilities
.supported_composite_alpha .supported_composite_alpha
.iter() .into_iter()
.next() .next()
.unwrap(), .unwrap(),
@ -305,10 +303,7 @@ fn main() {
]; ];
let vertex_buffer = CpuAccessibleBuffer::from_iter( let vertex_buffer = CpuAccessibleBuffer::from_iter(
&memory_allocator, &memory_allocator,
BufferUsage { BufferUsage::VERTEX_BUFFER,
vertex_buffer: true,
..BufferUsage::empty()
},
false, false,
vertices, vertices,
) )

View File

@ -26,6 +26,7 @@ use vulkano::{
}, },
device::{ device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
QueueFlags,
}, },
image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage}, image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage},
impl_vertex, impl_vertex,
@ -131,7 +132,8 @@ fn main() {
// We select a queue family that supports graphics operations. When drawing to // We select a queue family that supports graphics operations. When drawing to
// a window surface, as we do in this example, we also need to check that queues // a window surface, as we do in this example, we also need to check that queues
// in this queue family are capable of presenting images to the surface. // in this queue family are capable of presenting images to the surface.
q.queue_flags.graphics && p.surface_support(i as u32, &surface).unwrap_or(false) q.queue_flags.intersects(QueueFlags::GRAPHICS)
&& p.surface_support(i as u32, &surface).unwrap_or(false)
}) })
// The code here searches for the first queue family that is suitable. If none is // The code here searches for the first queue family that is suitable. If none is
// found, `None` is returned to `filter_map`, which disqualifies this physical // found, `None` is returned to `filter_map`, which disqualifies this physical
@ -241,16 +243,13 @@ fn main() {
// use that. // use that.
image_extent: window.inner_size().into(), image_extent: window.inner_size().into(),
image_usage: ImageUsage { image_usage: ImageUsage::COLOR_ATTACHMENT,
color_attachment: true,
..ImageUsage::empty()
},
// The alpha mode indicates how the alpha value of the final image will behave. For // The alpha mode indicates how the alpha value of the final image will behave. For
// example, you can choose whether the window will be opaque or transparent. // example, you can choose whether the window will be opaque or transparent.
composite_alpha: surface_capabilities composite_alpha: surface_capabilities
.supported_composite_alpha .supported_composite_alpha
.iter() .into_iter()
.next() .next()
.unwrap(), .unwrap(),
@ -285,10 +284,7 @@ fn main() {
]; ];
let vertex_buffer = CpuAccessibleBuffer::from_iter( let vertex_buffer = CpuAccessibleBuffer::from_iter(
&memory_allocator, &memory_allocator,
BufferUsage { BufferUsage::VERTEX_BUFFER,
vertex_buffer: true,
..BufferUsage::empty()
},
false, false,
vertices, vertices,
) )

View File

@ -165,38 +165,47 @@ fn write_descriptor_requirements(
}) })
}; };
let stages = { let stages = {
let ShaderStages { let stages_items = [
vertex, stages.intersects(ShaderStages::VERTEX).then(|| quote! {
tessellation_control, ::vulkano::shader::ShaderStages::VERTEX
tessellation_evaluation, }),
geometry, stages.intersects(ShaderStages::TESSELLATION_CONTROL).then(|| quote! {
fragment, ::vulkano::shader::ShaderStages::TESSELLATION_CONTROL
compute, }),
raygen, stages.intersects(ShaderStages::TESSELLATION_EVALUATION).then(|| quote! {
any_hit, ::vulkano::shader::ShaderStages::TESSELLATION_EVALUATION
closest_hit, }),
miss, stages.intersects(ShaderStages::GEOMETRY).then(|| quote! {
intersection, ::vulkano::shader::ShaderStages::GEOMETRY
callable, }),
_ne: _, stages.intersects(ShaderStages::FRAGMENT).then(|| quote! {
} = stages; ::vulkano::shader::ShaderStages::FRAGMENT
}),
stages.intersects(ShaderStages::COMPUTE).then(|| quote! {
::vulkano::shader::ShaderStages::COMPUTE
}),
stages.intersects(ShaderStages::RAYGEN).then(|| quote! {
::vulkano::shader::ShaderStages::RAYGEN
}),
stages.intersects(ShaderStages::ANY_HIT).then(|| quote! {
::vulkano::shader::ShaderStages::ANY_HIT
}),
stages.intersects(ShaderStages::CLOSEST_HIT).then(|| quote! {
::vulkano::shader::ShaderStages::CLOSEST_HIT
}),
stages.intersects(ShaderStages::MISS).then(|| quote! {
::vulkano::shader::ShaderStages::MISS
}),
stages.intersects(ShaderStages::INTERSECTION).then(|| quote! {
::vulkano::shader::ShaderStages::INTERSECTION
}),
stages.intersects(ShaderStages::CALLABLE).then(|| quote! {
::vulkano::shader::ShaderStages::CALLABLE
}),
].into_iter().flatten();
quote! { quote! {
::vulkano::shader::ShaderStages { #(#stages_items)|*
vertex: #vertex,
tessellation_control: #tessellation_control,
tessellation_evaluation: #tessellation_evaluation,
geometry: #geometry,
fragment: #fragment,
compute: #compute,
raygen: #raygen,
any_hit: #any_hit,
closest_hit: #closest_hit,
miss: #miss,
intersection: #intersection,
callable: #callable,
..::vulkano::shader::ShaderStages::empty()
}
} }
}; };
let storage_image_atomic = storage_image_atomic.iter(); let storage_image_atomic = storage_image_atomic.iter();
@ -243,38 +252,77 @@ fn write_push_constant_requirements(
stages, stages,
}) => { }) => {
let stages = { let stages = {
let ShaderStages { let stages_items = [
vertex, stages.intersects(ShaderStages::VERTEX).then(|| {
tessellation_control, quote! {
tessellation_evaluation, ::vulkano::shader::ShaderStages::VERTEX
geometry, }
fragment, }),
compute, stages
raygen, .intersects(ShaderStages::TESSELLATION_CONTROL)
any_hit, .then(|| {
closest_hit, quote! {
miss, ::vulkano::shader::ShaderStages::TESSELLATION_CONTROL
intersection, }
callable, }),
_ne: _, stages
} = stages; .intersects(ShaderStages::TESSELLATION_EVALUATION)
.then(|| {
quote! {
::vulkano::shader::ShaderStages::TESSELLATION_EVALUATION
}
}),
stages.intersects(ShaderStages::GEOMETRY).then(|| {
quote! {
::vulkano::shader::ShaderStages::GEOMETRY
}
}),
stages.intersects(ShaderStages::FRAGMENT).then(|| {
quote! {
::vulkano::shader::ShaderStages::FRAGMENT
}
}),
stages.intersects(ShaderStages::COMPUTE).then(|| {
quote! {
::vulkano::shader::ShaderStages::COMPUTE
}
}),
stages.intersects(ShaderStages::RAYGEN).then(|| {
quote! {
::vulkano::shader::ShaderStages::RAYGEN
}
}),
stages.intersects(ShaderStages::ANY_HIT).then(|| {
quote! {
::vulkano::shader::ShaderStages::ANY_HIT
}
}),
stages.intersects(ShaderStages::CLOSEST_HIT).then(|| {
quote! {
::vulkano::shader::ShaderStages::CLOSEST_HIT
}
}),
stages.intersects(ShaderStages::MISS).then(|| {
quote! {
::vulkano::shader::ShaderStages::MISS
}
}),
stages.intersects(ShaderStages::INTERSECTION).then(|| {
quote! {
::vulkano::shader::ShaderStages::INTERSECTION
}
}),
stages.intersects(ShaderStages::CALLABLE).then(|| {
quote! {
::vulkano::shader::ShaderStages::CALLABLE
}
}),
]
.into_iter()
.flatten();
quote! { quote! {
::vulkano::shader::ShaderStages { #(#stages_items)|*
vertex: #vertex,
tessellation_control: #tessellation_control,
tessellation_evaluation: #tessellation_evaluation,
geometry: #geometry,
fragment: #fragment,
compute: #compute,
raygen: #raygen,
any_hit: #any_hit,
closest_hit: #closest_hit,
miss: #miss,
intersection: #intersection,
callable: #callable,
..::vulkano::shader::ShaderStages::empty()
}
} }
}; };

View File

@ -11,7 +11,7 @@ use std::sync::Arc;
use vulkano::{ use vulkano::{
device::{ device::{
physical::{PhysicalDevice, PhysicalDeviceType}, physical::{PhysicalDevice, PhysicalDeviceType},
Device, DeviceCreateInfo, DeviceExtensions, Features, Queue, QueueCreateInfo, Device, DeviceCreateInfo, DeviceExtensions, Features, Queue, QueueCreateInfo, QueueFlags,
}, },
instance::{ instance::{
debug::{DebugUtilsMessenger, DebugUtilsMessengerCreateInfo}, debug::{DebugUtilsMessenger, DebugUtilsMessengerCreateInfo},
@ -199,7 +199,7 @@ impl VulkanoContext {
.iter() .iter()
.enumerate() .enumerate()
.map(|(i, q)| (i as u32, q)) .map(|(i, q)| (i as u32, q))
.find(|(_i, q)| q.queue_flags.graphics) .find(|(_i, q)| q.queue_flags.intersects(QueueFlags::GRAPHICS))
.map(|(i, _)| i) .map(|(i, _)| i)
.expect("Could not find a queue that supports graphics"); .expect("Could not find a queue that supports graphics");
// Try finding a separate queue for compute // Try finding a separate queue for compute
@ -208,7 +208,9 @@ impl VulkanoContext {
.iter() .iter()
.enumerate() .enumerate()
.map(|(i, q)| (i as u32, q)) .map(|(i, q)| (i as u32, q))
.find(|(i, q)| q.queue_flags.compute && *i != queue_family_graphics) .find(|(i, q)| {
q.queue_flags.intersects(QueueFlags::COMPUTE) && *i != queue_family_graphics
})
.map(|(i, _)| i); .map(|(i, _)| i);
let is_separate_compute_queue = queue_family_compute.is_some(); let is_separate_compute_queue = queue_family_compute.is_some();

View File

@ -124,13 +124,10 @@ impl VulkanoWindowRenderer {
min_image_count: surface_capabilities.min_image_count, min_image_count: surface_capabilities.min_image_count,
image_format, image_format,
image_extent, image_extent,
image_usage: ImageUsage { image_usage: ImageUsage::COLOR_ATTACHMENT,
color_attachment: true,
..ImageUsage::empty()
},
composite_alpha: surface_capabilities composite_alpha: surface_capabilities
.supported_composite_alpha .supported_composite_alpha
.iter() .into_iter()
.next() .next()
.unwrap(), .unwrap(),
..Default::default() ..Default::default()
@ -371,7 +368,7 @@ impl VulkanoWindowRenderer {
.collect::<Vec<usize>>(); .collect::<Vec<usize>>();
for i in resizable_views { for i in resizable_views {
let format = self.get_additional_image_view(i).format().unwrap(); let format = self.get_additional_image_view(i).format().unwrap();
let usage = *self.get_additional_image_view(i).usage(); let usage = self.get_additional_image_view(i).usage();
self.remove_additional_image_view(i); self.remove_additional_image_view(i);
self.add_additional_image_view(i, format, usage); self.add_additional_image_view(i, format, usage);
} }

View File

@ -63,78 +63,30 @@ fn formats_output(members: &[FormatMember]) -> TokenStream {
let enum_items = members.iter().map(|FormatMember { name, ffi_name, .. }| { let enum_items = members.iter().map(|FormatMember { name, ffi_name, .. }| {
quote! { #name = ash::vk::Format::#ffi_name.as_raw(), } quote! { #name = ash::vk::Format::#ffi_name.as_raw(), }
}); });
let aspects_color_items = members.iter().filter_map( let aspects_items = members.iter().map(
|FormatMember {
name, aspect_color, ..
}| {
if !aspect_color {
// Negated to reduce the length of the list
Some(name)
} else {
None
}
},
);
let aspects_depth_items = members.iter().filter_map(
|FormatMember {
name, aspect_depth, ..
}| {
if *aspect_depth {
Some(name)
} else {
None
}
},
);
let aspects_stencil_items = members.iter().filter_map(
|FormatMember { |FormatMember {
name, name,
aspect_color,
aspect_depth,
aspect_stencil, aspect_stencil,
..
}| {
if *aspect_stencil {
Some(name)
} else {
None
}
},
);
let aspects_plane0_items = members.iter().filter_map(
|FormatMember {
name,
aspect_plane0, aspect_plane0,
..
}| {
if *aspect_plane0 {
Some(name)
} else {
None
}
},
);
let aspects_plane1_items = members.iter().filter_map(
|FormatMember {
name,
aspect_plane1, aspect_plane1,
..
}| {
if *aspect_plane1 {
Some(name)
} else {
None
}
},
);
let aspects_plane2_items = members.iter().filter_map(
|FormatMember {
name,
aspect_plane2, aspect_plane2,
.. ..
}| { }| {
if *aspect_plane2 { let aspect_items = [
Some(name) aspect_color.then(|| quote! { crate::image::ImageAspects::COLOR }),
} else { aspect_depth.then(|| quote! { crate::image::ImageAspects::DEPTH }),
None aspect_stencil.then(|| quote! { crate::image::ImageAspects::STENCIL }),
aspect_plane0.then(|| quote! { crate::image::ImageAspects::PLANE_0 }),
aspect_plane1.then(|| quote! { crate::image::ImageAspects::PLANE_1 }),
aspect_plane2.then(|| quote! { crate::image::ImageAspects::PLANE_2 }),
]
.into_iter()
.flatten();
quote! {
Self::#name => #(#aspect_items)|*,
} }
}, },
); );
@ -381,15 +333,9 @@ fn formats_output(members: &[FormatMember]) -> TokenStream {
impl Format { impl Format {
/// Returns the aspects that images of this format have. /// Returns the aspects that images of this format have.
pub fn aspects(&self) -> ImageAspects { pub fn aspects(self) -> ImageAspects {
ImageAspects { match self {
color: !matches!(self, #(Format::#aspects_color_items)|* ), #(#aspects_items)*
depth: matches!(self, #(Format::#aspects_depth_items)|* ),
stencil: matches!(self, #(Format::#aspects_stencil_items)|* ),
plane0: matches!(self, #(Format::#aspects_plane0_items)|* ),
plane1: matches!(self, #(Format::#aspects_plane1_items)|* ),
plane2: matches!(self, #(Format::#aspects_plane2_items)|* ),
..ImageAspects::empty()
} }
} }
@ -403,7 +349,7 @@ fn formats_output(members: &[FormatMember]) -> TokenStream {
/// a single element. The 422 and 420 YCbCr formats have a block extent of [2, 1, 1] and /// a single element. The 422 and 420 YCbCr formats have a block extent of [2, 1, 1] and
/// [2, 2, 1] respectively, as the red and blue components are shared across multiple /// [2, 2, 1] respectively, as the red and blue components are shared across multiple
/// texels. /// texels.
pub fn block_extent(&self) -> [u32; 3] { pub fn block_extent(self) -> [u32; 3] {
match self { match self {
#(#block_extent_items)* #(#block_extent_items)*
_ => [1, 1, 1], _ => [1, 1, 1],
@ -420,7 +366,7 @@ fn formats_output(members: &[FormatMember]) -> TokenStream {
/// not have a well-defined size. Multi-planar formats store the color components /// not have a well-defined size. Multi-planar formats store the color components
/// disjointly in memory, and therefore do not have a well-defined size for all /// disjointly in memory, and therefore do not have a well-defined size for all
/// components as a whole. The individual planes do have a well-defined size. /// components as a whole. The individual planes do have a well-defined size.
pub fn block_size(&self) -> Option<DeviceSize> { pub fn block_size(self) -> Option<DeviceSize> {
match self { match self {
#(#block_size_items)* #(#block_size_items)*
_ => None, _ => None,
@ -430,7 +376,7 @@ fn formats_output(members: &[FormatMember]) -> TokenStream {
/// Returns the an opaque object representing the compatibility class of the format. /// Returns the an opaque object representing the compatibility class of the format.
/// This can be used to determine whether two formats are compatible for the purposes /// This can be used to determine whether two formats are compatible for the purposes
/// of certain Vulkan operations, such as image copying. /// of certain Vulkan operations, such as image copying.
pub fn compatibility(&self) -> FormatCompatibility { pub fn compatibility(self) -> FormatCompatibility {
FormatCompatibility(match self { FormatCompatibility(match self {
#(#compatibility_items)* #(#compatibility_items)*
}) })
@ -445,7 +391,7 @@ fn formats_output(members: &[FormatMember]) -> TokenStream {
/// For block-compressed formats, the number of bits in individual components is not /// For block-compressed formats, the number of bits in individual components is not
/// well-defined, and the return value is merely binary: 1 indicates a component /// well-defined, and the return value is merely binary: 1 indicates a component
/// that is present in the format, 0 indicates one that is absent. /// that is present in the format, 0 indicates one that is absent.
pub fn components(&self) -> [u8; 4] { pub fn components(self) -> [u8; 4] {
match self { match self {
#(#components_items)* #(#components_items)*
} }
@ -453,7 +399,7 @@ fn formats_output(members: &[FormatMember]) -> TokenStream {
/// Returns the block compression scheme used for this format, if any. Returns `None` if /// Returns the block compression scheme used for this format, if any. Returns `None` if
/// the format does not use compression. /// the format does not use compression.
pub fn compression(&self) -> Option<CompressionType> { pub fn compression(self) -> Option<CompressionType> {
match self { match self {
#(#compression_items)* #(#compression_items)*
_ => None, _ => None,
@ -464,7 +410,7 @@ fn formats_output(members: &[FormatMember]) -> TokenStream {
/// equivalent regular format of each plane. /// equivalent regular format of each plane.
/// ///
/// For non-planar formats, returns the empty slice. /// For non-planar formats, returns the empty slice.
pub fn planes(&self) -> &'static [Self] { pub fn planes(self) -> &'static [Self] {
match self { match self {
#(#planes_items)* #(#planes_items)*
_ => &[], _ => &[],
@ -473,7 +419,7 @@ fn formats_output(members: &[FormatMember]) -> TokenStream {
/// Returns the number of texels for a single texel block. For most formats, this is /// Returns the number of texels for a single texel block. For most formats, this is
/// the product of the `block_extent` elements, but for some it differs. /// the product of the `block_extent` elements, but for some it differs.
pub fn texels_per_block(&self) -> u8 { pub fn texels_per_block(self) -> u8 {
match self { match self {
#(#texels_per_block_items)* #(#texels_per_block_items)*
_ => 1, _ => 1,
@ -482,7 +428,7 @@ fn formats_output(members: &[FormatMember]) -> TokenStream {
/// Returns the numeric data type of the color aspect of this format. Returns `None` /// Returns the numeric data type of the color aspect of this format. Returns `None`
/// for depth/stencil formats. /// for depth/stencil formats.
pub fn type_color(&self) -> Option<NumericType> { pub fn type_color(self) -> Option<NumericType> {
match self { match self {
#(#type_color_items)* #(#type_color_items)*
_ => None, _ => None,
@ -491,7 +437,7 @@ fn formats_output(members: &[FormatMember]) -> TokenStream {
/// Returns the numeric data type of the depth aspect of this format. Returns `None` /// Returns the numeric data type of the depth aspect of this format. Returns `None`
/// color and stencil-only formats. /// color and stencil-only formats.
pub fn type_depth(&self) -> Option<NumericType> { pub fn type_depth(self) -> Option<NumericType> {
match self { match self {
#(#type_depth_items)* #(#type_depth_items)*
_ => None, _ => None,
@ -500,7 +446,7 @@ fn formats_output(members: &[FormatMember]) -> TokenStream {
/// Returns the numeric data type of the stencil aspect of this format. Returns `None` /// Returns the numeric data type of the stencil aspect of this format. Returns `None`
/// for color and depth-only formats. /// for color and depth-only formats.
pub fn type_stencil(&self) -> Option<NumericType> { pub fn type_stencil(self) -> Option<NumericType> {
match self { match self {
#(#type_stencil_items)* #(#type_stencil_items)*
_ => None, _ => None,
@ -513,7 +459,7 @@ fn formats_output(members: &[FormatMember]) -> TokenStream {
/// If an image view is created for one of the formats for which this function returns /// If an image view is created for one of the formats for which this function returns
/// `Some`, with the `color` aspect selected, then the view and any samplers that sample /// `Some`, with the `color` aspect selected, then the view and any samplers that sample
/// it must be created with an attached sampler YCbCr conversion object. /// it must be created with an attached sampler YCbCr conversion object.
pub fn ycbcr_chroma_sampling(&self) -> Option<ChromaSampling> { pub fn ycbcr_chroma_sampling(self) -> Option<ChromaSampling> {
match self { match self {
#(#ycbcr_chroma_sampling_items)* #(#ycbcr_chroma_sampling_items)*
_ => None, _ => None,

View File

@ -432,6 +432,7 @@ fn suffix_key(name: &str) -> u32 {
static ref VENDOR_SUFFIXES: Regex = Regex::new(r"(?:AMD|GOOGLE|INTEL|NV)$").unwrap(); static ref VENDOR_SUFFIXES: Regex = Regex::new(r"(?:AMD|GOOGLE|INTEL|NV)$").unwrap();
} }
#[allow(clippy::bool_to_int_with_if)]
if VENDOR_SUFFIXES.is_match(name) { if VENDOR_SUFFIXES.is_match(name) {
3 3
} else if name.ends_with("EXT") { } else if name.ends_with("EXT") {

View File

@ -63,7 +63,7 @@ enum Enable {
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
enum PropertyValue { enum PropertyValue {
Bool, Bool,
BoolMember(Ident), BoolMember(Vec<Ident>),
} }
fn spirv_reqs_output(members: &[SpirvReqsMember], extension: bool) -> TokenStream { fn spirv_reqs_output(members: &[SpirvReqsMember], extension: bool) -> TokenStream {
@ -97,7 +97,7 @@ fn spirv_reqs_output(members: &[SpirvReqsMember], extension: bool) -> TokenStrea
let access = match value { let access = match value {
PropertyValue::Bool => quote! {}, PropertyValue::Bool => quote! {},
PropertyValue::BoolMember(member) => quote! { PropertyValue::BoolMember(member) => quote! {
.map(|x| x.#member) .map(|x| x.intersects(#(#member)::*))
}, },
}; };
@ -249,9 +249,14 @@ fn make_enable(enable: &vk_parse::Enable) -> Option<(Enable, String)> {
let (value, description) = if property.value == "VK_TRUE" { let (value, description) = if property.value == "VK_TRUE" {
(PropertyValue::Bool, format!("property `{}`", property_name)) (PropertyValue::Bool, format!("property `{}`", property_name))
} else if let Some(member) = property.value.strip_prefix("VK_SUBGROUP_FEATURE_") { } else if let Some(member) = property.value.strip_prefix("VK_SUBGROUP_FEATURE_") {
let member = BIT.replace(member, "").to_snake_case(); let member = BIT.replace(member, "");
( (
PropertyValue::BoolMember(format_ident!("{}", member)), PropertyValue::BoolMember(
["crate", "device", "physical", "SubgroupFeatures", &member]
.into_iter()
.map(|s| format_ident!("{}", s))
.collect(),
),
format!("property `{}.{}`", property_name, member), format!("property `{}.{}`", property_name, member),
) )
} else { } else {

View File

@ -578,20 +578,14 @@ mod tests {
assert_should_panic!({ assert_should_panic!({
CpuAccessibleBuffer::from_data( CpuAccessibleBuffer::from_data(
&memory_allocator, &memory_allocator,
BufferUsage { BufferUsage::TRANSFER_DST,
transfer_dst: true,
..BufferUsage::empty()
},
false, false,
EMPTY, EMPTY,
) )
.unwrap(); .unwrap();
CpuAccessibleBuffer::from_iter( CpuAccessibleBuffer::from_iter(
&memory_allocator, &memory_allocator,
BufferUsage { BufferUsage::TRANSFER_DST,
transfer_dst: true,
..BufferUsage::empty()
},
false, false,
EMPTY.into_iter(), EMPTY.into_iter(),
) )

View File

@ -216,14 +216,7 @@ where
/// ///
/// - Panics if `T` has zero size. /// - Panics if `T` has zero size.
pub fn upload(allocator: Arc<A>) -> CpuBufferPool<T, A> { pub fn upload(allocator: Arc<A>) -> CpuBufferPool<T, A> {
CpuBufferPool::new( CpuBufferPool::new(allocator, BufferUsage::TRANSFER_SRC, MemoryUsage::Upload)
allocator,
BufferUsage {
transfer_src: true,
..BufferUsage::empty()
},
MemoryUsage::Upload,
)
} }
/// Builds a `CpuBufferPool` meant for simple downloads. /// Builds a `CpuBufferPool` meant for simple downloads.
@ -235,14 +228,7 @@ where
/// ///
/// - Panics if `T` has zero size. /// - Panics if `T` has zero size.
pub fn download(allocator: Arc<A>) -> CpuBufferPool<T, A> { pub fn download(allocator: Arc<A>) -> CpuBufferPool<T, A> {
CpuBufferPool::new( CpuBufferPool::new(allocator, BufferUsage::TRANSFER_DST, MemoryUsage::Download)
allocator,
BufferUsage {
transfer_dst: true,
..BufferUsage::empty()
},
MemoryUsage::Download,
)
} }
/// Builds a `CpuBufferPool` meant for usage as a uniform buffer. /// Builds a `CpuBufferPool` meant for usage as a uniform buffer.
@ -254,14 +240,7 @@ where
/// ///
/// - Panics if `T` has zero size. /// - Panics if `T` has zero size.
pub fn uniform_buffer(allocator: Arc<A>) -> CpuBufferPool<T, A> { pub fn uniform_buffer(allocator: Arc<A>) -> CpuBufferPool<T, A> {
CpuBufferPool::new( CpuBufferPool::new(allocator, BufferUsage::UNIFORM_BUFFER, MemoryUsage::Upload)
allocator,
BufferUsage {
uniform_buffer: true,
..BufferUsage::empty()
},
MemoryUsage::Upload,
)
} }
/// Builds a `CpuBufferPool` meant for usage as a vertex buffer. /// Builds a `CpuBufferPool` meant for usage as a vertex buffer.
@ -273,14 +252,7 @@ where
/// ///
/// - Panics if `T` has zero size. /// - Panics if `T` has zero size.
pub fn vertex_buffer(allocator: Arc<A>) -> CpuBufferPool<T, A> { pub fn vertex_buffer(allocator: Arc<A>) -> CpuBufferPool<T, A> {
CpuBufferPool::new( CpuBufferPool::new(allocator, BufferUsage::VERTEX_BUFFER, MemoryUsage::Upload)
allocator,
BufferUsage {
vertex_buffer: true,
..BufferUsage::empty()
},
MemoryUsage::Upload,
)
} }
/// Builds a `CpuBufferPool` meant for usage as a indirect buffer. /// Builds a `CpuBufferPool` meant for usage as a indirect buffer.
@ -292,14 +264,7 @@ where
/// ///
/// - Panics if `T` has zero size. /// - Panics if `T` has zero size.
pub fn indirect_buffer(allocator: Arc<A>) -> CpuBufferPool<T, A> { pub fn indirect_buffer(allocator: Arc<A>) -> CpuBufferPool<T, A> {
CpuBufferPool::new( CpuBufferPool::new(allocator, BufferUsage::INDIRECT_BUFFER, MemoryUsage::Upload)
allocator,
BufferUsage {
indirect_buffer: true,
..BufferUsage::empty()
},
MemoryUsage::Upload,
)
} }
} }
@ -538,7 +503,7 @@ where
let idx = current_buffer.next_index.load(Ordering::SeqCst); let idx = current_buffer.next_index.load(Ordering::SeqCst);
// Find the required alignment in bytes. // Find the required alignment in bytes.
let align_uniform = if self.buffer_usage.uniform_buffer { let align_uniform = if self.buffer_usage.intersects(BufferUsage::UNIFORM_BUFFER) {
self.device() self.device()
.physical_device() .physical_device()
.properties() .properties()
@ -546,7 +511,7 @@ where
} else { } else {
1 1
}; };
let align_storage = if self.buffer_usage.storage_buffer { let align_storage = if self.buffer_usage.intersects(BufferUsage::STORAGE_BUFFER) {
self.device() self.device()
.physical_device() .physical_device()
.properties() .properties()

View File

@ -83,7 +83,8 @@ use std::{
/// // Create a CPU accessible buffer initialized with the data. /// // Create a CPU accessible buffer initialized with the data.
/// let temporary_accessible_buffer = CpuAccessibleBuffer::from_iter( /// let temporary_accessible_buffer = CpuAccessibleBuffer::from_iter(
/// &memory_allocator, /// &memory_allocator,
/// BufferUsage { transfer_src: true, ..BufferUsage::empty() }, // Specify this buffer will be used as a transfer source. /// // Specify this buffer will be used as a transfer source.
/// BufferUsage::TRANSFER_SRC,
/// false, /// false,
/// data, /// data,
/// ) /// )
@ -93,11 +94,8 @@ use std::{
/// let device_local_buffer = DeviceLocalBuffer::<[f32]>::array( /// let device_local_buffer = DeviceLocalBuffer::<[f32]>::array(
/// &memory_allocator, /// &memory_allocator,
/// 10_000 as vulkano::DeviceSize, /// 10_000 as vulkano::DeviceSize,
/// BufferUsage { /// // Specify use as a storage buffer and transfer destination.
/// storage_buffer: true, /// BufferUsage::STORAGE_BUFFER | BufferUsage::TRANSFER_DST,
/// transfer_dst: true,
/// ..BufferUsage::empty()
/// }, // Specify use as a storage buffer and transfer destination.
/// device.active_queue_family_indices().iter().copied(), /// device.active_queue_family_indices().iter().copied(),
/// ) /// )
/// .unwrap(); /// .unwrap();
@ -182,10 +180,7 @@ where
{ {
unsafe { unsafe {
// We automatically set `transfer_dst` to true in order to avoid annoying errors. // We automatically set `transfer_dst` to true in order to avoid annoying errors.
let actual_usage = BufferUsage { let actual_usage = usage | BufferUsage::TRANSFER_DST;
transfer_dst: true,
..usage
};
let buffer = DeviceLocalBuffer::raw( let buffer = DeviceLocalBuffer::raw(
allocator, allocator,
@ -229,15 +224,8 @@ where
where where
A: CommandBufferAllocator, A: CommandBufferAllocator,
{ {
let source = CpuAccessibleBuffer::from_data( let source =
allocator, CpuAccessibleBuffer::from_data(allocator, BufferUsage::TRANSFER_SRC, false, data)?;
BufferUsage {
transfer_src: true,
..BufferUsage::empty()
},
false,
data,
)?;
DeviceLocalBuffer::from_buffer(allocator, source, usage, command_buffer_builder) DeviceLocalBuffer::from_buffer(allocator, source, usage, command_buffer_builder)
} }
} }
@ -267,15 +255,8 @@ where
D::IntoIter: ExactSizeIterator, D::IntoIter: ExactSizeIterator,
A: CommandBufferAllocator, A: CommandBufferAllocator,
{ {
let source = CpuAccessibleBuffer::from_iter( let source =
allocator, CpuAccessibleBuffer::from_iter(allocator, BufferUsage::TRANSFER_SRC, false, data)?;
BufferUsage {
transfer_src: true,
..BufferUsage::empty()
},
false,
data,
)?;
DeviceLocalBuffer::from_buffer(allocator, source, usage, command_buffer_builder) DeviceLocalBuffer::from_buffer(allocator, source, usage, command_buffer_builder)
} }
} }
@ -407,10 +388,7 @@ where
// VUID-VkMemoryAllocateInfo-pNext-00639 // VUID-VkMemoryAllocateInfo-pNext-00639
// Guaranteed because we always create a dedicated allocation // Guaranteed because we always create a dedicated allocation
let external_memory_handle_types = ExternalMemoryHandleTypes { let external_memory_handle_types = ExternalMemoryHandleTypes::OPAQUE_FD;
opaque_fd: true,
..ExternalMemoryHandleTypes::empty()
};
let raw_buffer = RawBuffer::new( let raw_buffer = RawBuffer::new(
allocator.device().clone(), allocator.device().clone(),
BufferCreateInfo { BufferCreateInfo {
@ -570,24 +548,14 @@ mod tests {
let buffer = DeviceLocalBuffer::from_data( let buffer = DeviceLocalBuffer::from_data(
&memory_allocator, &memory_allocator,
12u32, 12u32,
BufferUsage { BufferUsage::TRANSFER_SRC,
transfer_src: true,
..BufferUsage::empty()
},
&mut command_buffer_builder, &mut command_buffer_builder,
) )
.unwrap(); .unwrap();
let destination = CpuAccessibleBuffer::from_data( let destination =
&memory_allocator, CpuAccessibleBuffer::from_data(&memory_allocator, BufferUsage::TRANSFER_DST, false, 0)
BufferUsage { .unwrap();
transfer_dst: true,
..BufferUsage::empty()
},
false,
0,
)
.unwrap();
command_buffer_builder command_buffer_builder
.copy_buffer(CopyBufferInfo::buffers(buffer, destination.clone())) .copy_buffer(CopyBufferInfo::buffers(buffer, destination.clone()))
@ -621,20 +589,14 @@ mod tests {
let buffer = DeviceLocalBuffer::from_iter( let buffer = DeviceLocalBuffer::from_iter(
&allocator, &allocator,
(0..512u32).map(|n| n * 2), (0..512u32).map(|n| n * 2),
BufferUsage { BufferUsage::TRANSFER_SRC,
transfer_src: true,
..BufferUsage::empty()
},
&mut command_buffer_builder, &mut command_buffer_builder,
) )
.unwrap(); .unwrap();
let destination = CpuAccessibleBuffer::from_iter( let destination = CpuAccessibleBuffer::from_iter(
&allocator, &allocator,
BufferUsage { BufferUsage::TRANSFER_DST,
transfer_dst: true,
..BufferUsage::empty()
},
false, false,
(0..512).map(|_| 0u32), (0..512).map(|_| 0u32),
) )
@ -676,10 +638,7 @@ mod tests {
DeviceLocalBuffer::from_data( DeviceLocalBuffer::from_data(
&allocator, &allocator,
(), (),
BufferUsage { BufferUsage::TRANSFER_DST,
transfer_dst: true,
..BufferUsage::empty()
},
&mut command_buffer_builder, &mut command_buffer_builder,
) )
.unwrap(); .unwrap();

View File

@ -106,8 +106,9 @@ mod traits;
mod usage; mod usage;
vulkan_bitflags! { vulkan_bitflags! {
/// Flags to be set when creating a buffer.
#[non_exhaustive] #[non_exhaustive]
/// Flags to be set when creating a buffer.
BufferCreateFlags = BufferCreateFlags(u32); BufferCreateFlags = BufferCreateFlags(u32);
/* /*
@ -118,7 +119,7 @@ vulkan_bitflags! {
/// ///
/// [`bind_memory`]: sys::RawBuffer::bind_memory /// [`bind_memory`]: sys::RawBuffer::bind_memory
/// [`sparse_binding`]: crate::device::Features::sparse_binding /// [`sparse_binding`]: crate::device::Features::sparse_binding
sparse_binding = SPARSE_BINDING, SPARSE_BINDING = SPARSE_BINDING,
/// The buffer can be used without being fully resident in memory at the time of use. /// The buffer can be used without being fully resident in memory at the time of use.
/// ///
@ -127,7 +128,7 @@ vulkan_bitflags! {
/// The [`sparse_residency_buffer`] feature must be enabled on the device. /// The [`sparse_residency_buffer`] feature must be enabled on the device.
/// ///
/// [`sparse_residency_buffer`]: crate::device::Features::sparse_residency_buffer /// [`sparse_residency_buffer`]: crate::device::Features::sparse_residency_buffer
sparse_residency = SPARSE_RESIDENCY, SPARSE_RESIDENCY = SPARSE_RESIDENCY,
/// The buffer's memory can alias with another buffer or a different part of the same buffer. /// The buffer's memory can alias with another buffer or a different part of the same buffer.
/// ///
@ -136,13 +137,13 @@ vulkan_bitflags! {
/// The [`sparse_residency_aliased`] feature must be enabled on the device. /// The [`sparse_residency_aliased`] feature must be enabled on the device.
/// ///
/// [`sparse_residency_aliased`]: crate::device::Features::sparse_residency_aliased /// [`sparse_residency_aliased`]: crate::device::Features::sparse_residency_aliased
sparse_aliased = SPARSE_ALIASED, SPARSE_ALIASED = SPARSE_ALIASED,
/// The buffer is protected, and can only be used in combination with protected memory and other /// The buffer is protected, and can only be used in combination with protected memory and other
/// protected objects. /// protected objects.
/// ///
/// The device API version must be at least 1.1. /// The device API version must be at least 1.1.
protected = PROTECTED { PROTECTED = PROTECTED {
api_version: V1_1, api_version: V1_1,
}, },
@ -150,7 +151,7 @@ vulkan_bitflags! {
/// ///
/// The device API version must be at least 1.2, or either the [`khr_buffer_device_address`] or /// The device API version must be at least 1.2, or either the [`khr_buffer_device_address`] or
/// [`ext_buffer_device_address`] extension must be enabled on the device. /// [`ext_buffer_device_address`] extension must be enabled on the device.
device_address_capture_replay = DEVICE_ADDRESS_CAPTURE_REPLAY { DEVICE_ADDRESS_CAPTURE_REPLAY = DEVICE_ADDRESS_CAPTURE_REPLAY {
api_version: V1_2, api_version: V1_2,
device_extensions: [khr_buffer_device_address, ext_buffer_device_address], device_extensions: [khr_buffer_device_address, ext_buffer_device_address],
}, },

View File

@ -21,7 +21,8 @@ use crate::{
device::{Device, DeviceOwned}, device::{Device, DeviceOwned},
memory::{ memory::{
allocator::{AllocationCreationError, MemoryAlloc}, allocator::{AllocationCreationError, MemoryAlloc},
DedicatedTo, ExternalMemoryHandleType, ExternalMemoryHandleTypes, MemoryRequirements, DedicatedTo, ExternalMemoryHandleType, ExternalMemoryHandleTypes, MemoryAllocateFlags,
MemoryPropertyFlags, MemoryRequirements,
}, },
range_map::RangeMap, range_map::RangeMap,
sync::{AccessError, CurrentAccess, Sharing}, sync::{AccessError, CurrentAccess, Sharing},
@ -126,7 +127,8 @@ impl RawBuffer {
// VUID-VkBufferCreateInfo-flags-00916 // VUID-VkBufferCreateInfo-flags-00916
if sparse_level.sparse_residency && !device.enabled_features().sparse_residency_buffer { if sparse_level.sparse_residency && !device.enabled_features().sparse_residency_buffer {
return Err(BufferError::RequirementNotMet { return Err(BufferError::RequirementNotMet {
required_for: "`create_info.sparse` is `Some(sparse_level)`, where `sparse_level.sparse_residency` is set", required_for: "`create_info.sparse` is `Some(sparse_level)`, where \
`sparse_level` contains `BufferCreateFlags::SPARSE_RESIDENCY`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["sparse_residency_buffer"], features: &["sparse_residency_buffer"],
..Default::default() ..Default::default()
@ -137,7 +139,8 @@ impl RawBuffer {
// VUID-VkBufferCreateInfo-flags-00917 // VUID-VkBufferCreateInfo-flags-00917
if sparse_level.sparse_aliased && !device.enabled_features().sparse_residency_aliased { if sparse_level.sparse_aliased && !device.enabled_features().sparse_residency_aliased {
return Err(BufferError::RequirementNotMet { return Err(BufferError::RequirementNotMet {
required_for: "`create_info.sparse` is `Some(sparse_level)`, where `sparse_level.sparse_aliased` is set", required_for: "`create_info.sparse` is `Some(sparse_level)`, where \
`sparse_level` contains `BufferCreateFlags::SPARSE_ALIASED`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["sparse_residency_aliased"], features: &["sparse_residency_aliased"],
..Default::default() ..Default::default()
@ -302,21 +305,21 @@ impl RawBuffer {
// We have to manually enforce some additional requirements for some buffer types. // We have to manually enforce some additional requirements for some buffer types.
let properties = device.physical_device().properties(); let properties = device.physical_device().properties();
if usage.uniform_texel_buffer || usage.storage_texel_buffer { if usage.intersects(BufferUsage::UNIFORM_TEXEL_BUFFER | BufferUsage::STORAGE_TEXEL_BUFFER) {
memory_requirements.alignment = align( memory_requirements.alignment = align(
memory_requirements.alignment, memory_requirements.alignment,
properties.min_texel_buffer_offset_alignment, properties.min_texel_buffer_offset_alignment,
); );
} }
if usage.storage_buffer { if usage.intersects(BufferUsage::STORAGE_BUFFER) {
memory_requirements.alignment = align( memory_requirements.alignment = align(
memory_requirements.alignment, memory_requirements.alignment,
properties.min_storage_buffer_offset_alignment, properties.min_storage_buffer_offset_alignment,
); );
} }
if usage.uniform_buffer { if usage.intersects(BufferUsage::UNIFORM_BUFFER) {
memory_requirements.alignment = align( memory_requirements.alignment = align(
memory_requirements.alignment, memory_requirements.alignment,
properties.min_uniform_buffer_offset_alignment, properties.min_uniform_buffer_offset_alignment,
@ -479,7 +482,10 @@ impl RawBuffer {
} }
// VUID-VkBindBufferMemoryInfo-None-01899 // VUID-VkBindBufferMemoryInfo-None-01899
if memory_type.property_flags.protected { if memory_type
.property_flags
.intersects(MemoryPropertyFlags::PROTECTED)
{
return Err(BufferError::MemoryProtectedMismatch { return Err(BufferError::MemoryProtectedMismatch {
buffer_protected: false, buffer_protected: false,
memory_protected: true, memory_protected: true,
@ -490,7 +496,7 @@ impl RawBuffer {
if !memory.export_handle_types().is_empty() if !memory.export_handle_types().is_empty()
&& !memory && !memory
.export_handle_types() .export_handle_types()
.intersects(&self.external_memory_handle_types) .intersects(self.external_memory_handle_types)
{ {
return Err(BufferError::MemoryExternalHandleTypesDisjoint { return Err(BufferError::MemoryExternalHandleTypesDisjoint {
buffer_handle_types: self.external_memory_handle_types, buffer_handle_types: self.external_memory_handle_types,
@ -501,7 +507,7 @@ impl RawBuffer {
if let Some(handle_type) = memory.imported_handle_type() { if let Some(handle_type) = memory.imported_handle_type() {
// VUID-VkBindBufferMemoryInfo-memory-02985 // VUID-VkBindBufferMemoryInfo-memory-02985
if !ExternalMemoryHandleTypes::from(handle_type) if !ExternalMemoryHandleTypes::from(handle_type)
.intersects(&self.external_memory_handle_types) .intersects(self.external_memory_handle_types)
{ {
return Err(BufferError::MemoryImportedHandleTypeNotEnabled { return Err(BufferError::MemoryImportedHandleTypeNotEnabled {
buffer_handle_types: self.external_memory_handle_types, buffer_handle_types: self.external_memory_handle_types,
@ -512,8 +518,10 @@ impl RawBuffer {
// VUID-VkBindBufferMemoryInfo-bufferDeviceAddress-03339 // VUID-VkBindBufferMemoryInfo-bufferDeviceAddress-03339
if !self.device.enabled_extensions().ext_buffer_device_address if !self.device.enabled_extensions().ext_buffer_device_address
&& self.usage.shader_device_address && self.usage.intersects(BufferUsage::SHADER_DEVICE_ADDRESS)
&& !memory.flags().device_address && !memory
.flags()
.intersects(MemoryAllocateFlags::DEVICE_ADDRESS)
{ {
return Err(BufferError::MemoryBufferDeviceAddressNotSupported); return Err(BufferError::MemoryBufferDeviceAddressNotSupported);
} }
@ -660,11 +668,12 @@ pub struct BufferCreateInfo {
/// The external memory handle types that are going to be used with the buffer. /// The external memory handle types that are going to be used with the buffer.
/// ///
/// If any of the fields in this value are set, the device must either support API version 1.1 /// If this value is not empty, then the device API version must be at least 1.1, or the
/// or the [`khr_external_memory`](crate::device::DeviceExtensions::khr_external_memory) /// [`khr_external_memory`] extension must be enabled on the device.
/// extension must be enabled.
/// ///
/// The default value is [`ExternalMemoryHandleTypes::empty()`]. /// The default value is [`ExternalMemoryHandleTypes::empty()`].
///
/// [`khr_external_memory`]: crate::device::DeviceExtensions::khr_external_memory
pub external_memory_handle_types: ExternalMemoryHandleTypes, pub external_memory_handle_types: ExternalMemoryHandleTypes,
pub _ne: crate::NonExhaustive, pub _ne: crate::NonExhaustive,
@ -1429,10 +1438,7 @@ mod tests {
device.clone(), device.clone(),
BufferCreateInfo { BufferCreateInfo {
size: 128, size: 128,
usage: BufferUsage { usage: BufferUsage::TRANSFER_DST,
transfer_dst: true,
..BufferUsage::empty()
},
..Default::default() ..Default::default()
}, },
) )
@ -1453,10 +1459,7 @@ mod tests {
BufferCreateInfo { BufferCreateInfo {
size: 128, size: 128,
sparse: Some(BufferCreateFlags::empty()), sparse: Some(BufferCreateFlags::empty()),
usage: BufferUsage { usage: BufferUsage::transfer_dst,
transfer_dst: true,
..BufferUsage::empty()
},
..Default::default() ..Default::default()
}, },
) { ) {
@ -1480,10 +1483,7 @@ mod tests {
sparse_aliased: false, sparse_aliased: false,
..Default::default() ..Default::default()
}), }),
usage: BufferUsage { usage: BufferUsage::transfer_dst,
transfer_dst: true,
..BufferUsage::empty()
},
..Default::default() ..Default::default()
}, },
) { ) {
@ -1507,10 +1507,7 @@ mod tests {
sparse_aliased: true, sparse_aliased: true,
..Default::default() ..Default::default()
}), }),
usage: BufferUsage { usage: BufferUsage::transfer_dst,
transfer_dst: true,
..BufferUsage::empty()
},
..Default::default() ..Default::default()
}, },
) { ) {
@ -1532,10 +1529,7 @@ mod tests {
device, device,
BufferCreateInfo { BufferCreateInfo {
size: 0, size: 0,
usage: BufferUsage { usage: BufferUsage::TRANSFER_DST,
transfer_dst: true,
..BufferUsage::empty()
},
..Default::default() ..Default::default()
}, },
) )

View File

@ -81,7 +81,7 @@ pub unsafe trait BufferAccess: DeviceOwned + Send + Sync {
// VUID-vkGetBufferDeviceAddress-bufferDeviceAddress-03324 // VUID-vkGetBufferDeviceAddress-bufferDeviceAddress-03324
if !device.enabled_features().buffer_device_address { if !device.enabled_features().buffer_device_address {
return Err(BufferDeviceAddressError::RequirementNotMet { return Err(BufferDeviceAddressError::RequirementNotMet {
required_for: "`raw_device_address`", required_for: "`BufferAccess::raw_device_address`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["buffer_device_address"], features: &["buffer_device_address"],
..Default::default() ..Default::default()
@ -90,7 +90,11 @@ pub unsafe trait BufferAccess: DeviceOwned + Send + Sync {
} }
// VUID-VkBufferDeviceAddressInfo-buffer-02601 // VUID-VkBufferDeviceAddressInfo-buffer-02601
if !inner.buffer.usage().shader_device_address { if !inner
.buffer
.usage()
.intersects(BufferUsage::SHADER_DEVICE_ADDRESS)
{
return Err(BufferDeviceAddressError::BufferMissingUsage); return Err(BufferDeviceAddressError::BufferMissingUsage);
} }

View File

@ -10,100 +10,101 @@
use crate::macros::vulkan_bitflags; use crate::macros::vulkan_bitflags;
vulkan_bitflags! { vulkan_bitflags! {
#[non_exhaustive]
/// Describes how a buffer is going to be used. This is **not** just an optimization. /// Describes how a buffer is going to be used. This is **not** just an optimization.
/// ///
/// If you try to use a buffer in a way that you didn't declare, an error will be returned. /// If you try to use a buffer in a way that you didn't declare, an error will be returned.
#[non_exhaustive]
BufferUsage = BufferUsageFlags(u32); BufferUsage = BufferUsageFlags(u32);
/// The buffer can be used as a source for transfer, blit, resolve and clear commands. /// The buffer can be used as a source for transfer, blit, resolve and clear commands.
transfer_src = TRANSFER_SRC, TRANSFER_SRC = TRANSFER_SRC,
/// The buffer can be used as a destination for transfer, blit, resolve and clear commands. /// The buffer can be used as a destination for transfer, blit, resolve and clear commands.
transfer_dst = TRANSFER_DST, TRANSFER_DST = TRANSFER_DST,
/// The buffer can be used as a uniform texel buffer in a descriptor set. /// The buffer can be used as a uniform texel buffer in a descriptor set.
uniform_texel_buffer = UNIFORM_TEXEL_BUFFER, UNIFORM_TEXEL_BUFFER = UNIFORM_TEXEL_BUFFER,
/// The buffer can be used as a storage texel buffer in a descriptor set. /// The buffer can be used as a storage texel buffer in a descriptor set.
storage_texel_buffer = STORAGE_TEXEL_BUFFER, STORAGE_TEXEL_BUFFER = STORAGE_TEXEL_BUFFER,
/// The buffer can be used as a uniform buffer in a descriptor set. /// The buffer can be used as a uniform buffer in a descriptor set.
uniform_buffer = UNIFORM_BUFFER, UNIFORM_BUFFER = UNIFORM_BUFFER,
/// The buffer can be used as a storage buffer in a descriptor set. /// The buffer can be used as a storage buffer in a descriptor set.
storage_buffer = STORAGE_BUFFER, STORAGE_BUFFER = STORAGE_BUFFER,
/// The buffer can be used as an index buffer. /// The buffer can be used as an index buffer.
index_buffer = INDEX_BUFFER, INDEX_BUFFER = INDEX_BUFFER,
/// The buffer can be used as a vertex or instance buffer. /// The buffer can be used as a vertex or instance buffer.
vertex_buffer = VERTEX_BUFFER, VERTEX_BUFFER = VERTEX_BUFFER,
/// The buffer can be used as an indirect buffer. /// The buffer can be used as an indirect buffer.
indirect_buffer = INDIRECT_BUFFER, INDIRECT_BUFFER = INDIRECT_BUFFER,
/// The buffer's device address can be retrieved. /// The buffer's device address can be retrieved.
/// ///
/// A buffer created with this usage can only be bound to device memory allocated with the /// A buffer created with this usage can only be bound to device memory allocated with the
/// [`device_address`] flag set unless the [`ext_buffer_device_address`] extension is enabled /// [`MemoryAllocateFlags::DEVICE_ADDRESS`] flag, unless the [`ext_buffer_device_address`]
/// on the device. /// extension is enabled on the device.
/// ///
/// [`device_address`]: crate::memory::MemoryAllocateFlags::device_address /// [`MemoryAllocateFlags::DEVICE_ADDRESS`]: crate::memory::MemoryAllocateFlags::DEVICE_ADDRESS
/// [`ext_buffer_device_address`]: crate::device::DeviceExtensions::ext_buffer_device_address /// [`ext_buffer_device_address`]: crate::device::DeviceExtensions::ext_buffer_device_address
shader_device_address = SHADER_DEVICE_ADDRESS { SHADER_DEVICE_ADDRESS = SHADER_DEVICE_ADDRESS {
api_version: V1_2, api_version: V1_2,
device_extensions: [khr_buffer_device_address, ext_buffer_device_address], device_extensions: [khr_buffer_device_address, ext_buffer_device_address],
}, },
/* /*
// TODO: document // TODO: document
video_decode_src = VIDEO_DECODE_SRC_KHR { VIDEO_DECODE_SRC = VIDEO_DECODE_SRC_KHR {
device_extensions: [khr_video_decode_queue], device_extensions: [khr_video_decode_queue],
}, },
// TODO: document // TODO: document
video_decode_dst = VIDEO_DECODE_DST_KHR { VIDEO_DECODE_DST = VIDEO_DECODE_DST_KHR {
device_extensions: [khr_video_decode_queue], device_extensions: [khr_video_decode_queue],
}, },
// TODO: document // TODO: document
transform_feedback_buffer = TRANSFORM_FEEDBACK_BUFFER_EXT { TRANSFORM_FEEDBACK_BUFFER = TRANSFORM_FEEDBACK_BUFFER_EXT {
device_extensions: [ext_transform_feedback], device_extensions: [ext_transform_feedback],
}, },
// TODO: document // TODO: document
transform_feedback_counter_buffer = TRANSFORM_FEEDBACK_COUNTER_BUFFER_EXT { TRANSFORM_FEEDBACK_COUNTER_BUFFER = TRANSFORM_FEEDBACK_COUNTER_BUFFER_EXT {
device_extensions: [ext_transform_feedback], device_extensions: [ext_transform_feedback],
}, },
// TODO: document // TODO: document
conditional_rendering = CONDITIONAL_RENDERING_EXT { CONDITIONAL_RENDERING = CONDITIONAL_RENDERING_EXT {
device_extensions: [ext_conditional_rendering], device_extensions: [ext_conditional_rendering],
}, },
// TODO: document // TODO: document
acceleration_structure_build_input_read_only = ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_KHR { ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_KHR = ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_KHR {
device_extensions: [khr_acceleration_structure], device_extensions: [khr_acceleration_structure],
}, },
// TODO: document // TODO: document
acceleration_structure_storage = ACCELERATION_STRUCTURE_STORAGE_KHR { ACCELERATION_STRUCTURE_STORAGE = ACCELERATION_STRUCTURE_STORAGE_KHR {
device_extensions: [khr_acceleration_structure], device_extensions: [khr_acceleration_structure],
}, },
// TODO: document // TODO: document
shader_binding_table = SHADER_BINDING_TABLE_KHR { SHADER_BINDING_TABLE = SHADER_BINDING_TABLE_KHR {
device_extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], device_extensions: [khr_ray_tracing_pipeline, nv_ray_tracing],
}, },
// TODO: document // TODO: document
video_encode_dst = VIDEO_ENCODE_DST_KHR { VIDEO_ENCODE_DST = VIDEO_ENCODE_DST_KHR {
device_extensions: [khr_video_encode_queue], device_extensions: [khr_video_encode_queue],
}, },
// TODO: document // TODO: document
video_encode_src = VIDEO_ENCODE_SRC_KHR { VIDEO_ENCODE_SRC = VIDEO_ENCODE_SRC_KHR {
device_extensions: [khr_video_encode_queue], device_extensions: [khr_video_encode_queue],
}, },
*/ */

View File

@ -26,15 +26,10 @@
//! //!
//! # let queue: Arc<vulkano::device::Queue> = return; //! # let queue: Arc<vulkano::device::Queue> = return;
//! # let memory_allocator: vulkano::memory::allocator::StandardMemoryAllocator = return; //! # let memory_allocator: vulkano::memory::allocator::StandardMemoryAllocator = return;
//! let usage = BufferUsage {
//! storage_texel_buffer: true,
//! ..BufferUsage::empty()
//! };
//!
//! let buffer = DeviceLocalBuffer::<[u32]>::array( //! let buffer = DeviceLocalBuffer::<[u32]>::array(
//! &memory_allocator, //! &memory_allocator,
//! 128, //! 128,
//! usage, //! BufferUsage::STORAGE_TEXEL_BUFFER,
//! [queue.queue_family_index()], //! [queue.queue_family_index()],
//! ) //! )
//! .unwrap(); //! .unwrap();
@ -48,7 +43,7 @@
//! .unwrap(); //! .unwrap();
//! ``` //! ```
use super::{BufferAccess, BufferAccessObject, BufferInner}; use super::{BufferAccess, BufferAccessObject, BufferInner, BufferUsage};
use crate::{ use crate::{
device::{Device, DeviceOwned}, device::{Device, DeviceOwned},
format::{Format, FormatFeatures}, format::{Format, FormatFeatures},
@ -107,7 +102,9 @@ where
format.validate_device(device)?; format.validate_device(device)?;
// VUID-VkBufferViewCreateInfo-buffer-00932 // VUID-VkBufferViewCreateInfo-buffer-00932
if !(inner_buffer.usage().uniform_texel_buffer || inner_buffer.usage().storage_texel_buffer) if !inner_buffer
.usage()
.intersects(BufferUsage::UNIFORM_TEXEL_BUFFER | BufferUsage::STORAGE_TEXEL_BUFFER)
{ {
return Err(BufferViewCreationError::BufferMissingUsage); return Err(BufferViewCreationError::BufferMissingUsage);
} }
@ -121,12 +118,20 @@ where
}; };
// VUID-VkBufferViewCreateInfo-buffer-00933 // VUID-VkBufferViewCreateInfo-buffer-00933
if inner_buffer.usage().uniform_texel_buffer && !format_features.uniform_texel_buffer { if inner_buffer
.usage()
.intersects(BufferUsage::UNIFORM_TEXEL_BUFFER)
&& !format_features.intersects(FormatFeatures::UNIFORM_TEXEL_BUFFER)
{
return Err(BufferViewCreationError::UnsupportedFormat); return Err(BufferViewCreationError::UnsupportedFormat);
} }
// VUID-VkBufferViewCreateInfo-buffer-00934 // VUID-VkBufferViewCreateInfo-buffer-00934
if inner_buffer.usage().storage_texel_buffer && !format_features.storage_texel_buffer { if inner_buffer
.usage()
.intersects(BufferUsage::STORAGE_TEXEL_BUFFER)
&& !format_features.intersects(FormatFeatures::STORAGE_TEXEL_BUFFER)
{
return Err(BufferViewCreationError::UnsupportedFormat); return Err(BufferViewCreationError::UnsupportedFormat);
} }
@ -156,7 +161,10 @@ where
block_size block_size
}; };
if inner_buffer.usage().storage_texel_buffer { if inner_buffer
.usage()
.intersects(BufferUsage::STORAGE_TEXEL_BUFFER)
{
let mut required_alignment = properties let mut required_alignment = properties
.storage_texel_buffer_offset_alignment_bytes .storage_texel_buffer_offset_alignment_bytes
.unwrap(); .unwrap();
@ -177,7 +185,10 @@ where
} }
} }
if inner_buffer.usage().uniform_texel_buffer { if inner_buffer
.usage()
.intersects(BufferUsage::UNIFORM_TEXEL_BUFFER)
{
let mut required_alignment = properties let mut required_alignment = properties
.uniform_texel_buffer_offset_alignment_bytes .uniform_texel_buffer_offset_alignment_bytes
.unwrap(); .unwrap();
@ -416,7 +427,7 @@ pub unsafe trait BufferViewAbstract:
fn format(&self) -> Option<Format>; fn format(&self) -> Option<Format>;
/// Returns the features supported by the buffer view's format. /// Returns the features supported by the buffer view's format.
fn format_features(&self) -> &FormatFeatures; fn format_features(&self) -> FormatFeatures;
/// Returns the byte range of the wrapped buffer that this view exposes. /// Returns the byte range of the wrapped buffer that this view exposes.
fn range(&self) -> Range<DeviceSize>; fn range(&self) -> Range<DeviceSize>;
@ -435,8 +446,8 @@ where
self.format self.format
} }
fn format_features(&self) -> &FormatFeatures { fn format_features(&self) -> FormatFeatures {
&self.format_features self.format_features
} }
fn range(&self) -> Range<DeviceSize> { fn range(&self) -> Range<DeviceSize> {
@ -475,10 +486,7 @@ mod tests {
let (device, queue) = gfx_dev_and_queue!(); let (device, queue) = gfx_dev_and_queue!();
let memory_allocator = StandardMemoryAllocator::new_default(device); let memory_allocator = StandardMemoryAllocator::new_default(device);
let usage = BufferUsage { let usage = BufferUsage::UNIFORM_TEXEL_BUFFER;
uniform_texel_buffer: true,
..BufferUsage::empty()
};
let buffer = DeviceLocalBuffer::<[[u8; 4]]>::array( let buffer = DeviceLocalBuffer::<[[u8; 4]]>::array(
&memory_allocator, &memory_allocator,
@ -503,10 +511,7 @@ mod tests {
let (device, queue) = gfx_dev_and_queue!(); let (device, queue) = gfx_dev_and_queue!();
let memory_allocator = StandardMemoryAllocator::new_default(device); let memory_allocator = StandardMemoryAllocator::new_default(device);
let usage = BufferUsage { let usage = BufferUsage::STORAGE_TEXEL_BUFFER;
storage_texel_buffer: true,
..BufferUsage::empty()
};
let buffer = DeviceLocalBuffer::<[[u8; 4]]>::array( let buffer = DeviceLocalBuffer::<[[u8; 4]]>::array(
&memory_allocator, &memory_allocator,
@ -531,10 +536,7 @@ mod tests {
let (device, queue) = gfx_dev_and_queue!(); let (device, queue) = gfx_dev_and_queue!();
let memory_allocator = StandardMemoryAllocator::new_default(device); let memory_allocator = StandardMemoryAllocator::new_default(device);
let usage = BufferUsage { let usage = BufferUsage::STORAGE_TEXEL_BUFFER;
storage_texel_buffer: true,
..BufferUsage::empty()
};
let buffer = DeviceLocalBuffer::<[u32]>::array( let buffer = DeviceLocalBuffer::<[u32]>::array(
&memory_allocator, &memory_allocator,
@ -562,10 +564,7 @@ mod tests {
let buffer = DeviceLocalBuffer::<[[u8; 4]]>::array( let buffer = DeviceLocalBuffer::<[[u8; 4]]>::array(
&memory_allocator, &memory_allocator,
128, 128,
BufferUsage { BufferUsage::TRANSFER_DST, // Dummy value
transfer_dst: true, // Dummy value
..BufferUsage::empty()
},
[queue.queue_family_index()], [queue.queue_family_index()],
) )
.unwrap(); .unwrap();
@ -587,11 +586,7 @@ mod tests {
let (device, queue) = gfx_dev_and_queue!(); let (device, queue) = gfx_dev_and_queue!();
let memory_allocator = StandardMemoryAllocator::new_default(device); let memory_allocator = StandardMemoryAllocator::new_default(device);
let usage = BufferUsage { let usage = BufferUsage::UNIFORM_TEXEL_BUFFER | BufferUsage::STORAGE_TEXEL_BUFFER;
uniform_texel_buffer: true,
storage_texel_buffer: true,
..BufferUsage::empty()
};
let buffer = DeviceLocalBuffer::<[[f64; 4]]>::array( let buffer = DeviceLocalBuffer::<[[f64; 4]]>::array(
&memory_allocator, &memory_allocator,

View File

@ -23,8 +23,8 @@ use crate::{
buffer::{sys::Buffer, BufferAccess}, buffer::{sys::Buffer, BufferAccess},
command_buffer::CommandBufferInheritanceRenderingInfo, command_buffer::CommandBufferInheritanceRenderingInfo,
device::{Device, DeviceOwned, Queue, QueueFamilyProperties}, device::{Device, DeviceOwned, Queue, QueueFamilyProperties},
format::Format, format::{Format, FormatFeatures},
image::{sys::Image, ImageAccess, ImageLayout, ImageSubresourceRange}, image::{sys::Image, ImageAccess, ImageAspects, ImageLayout, ImageSubresourceRange},
query::{QueryControlFlags, QueryType}, query::{QueryControlFlags, QueryType},
render_pass::{Framebuffer, Subpass}, render_pass::{Framebuffer, Subpass},
sync::{AccessCheckError, AccessFlags, PipelineMemoryAccess, PipelineStages}, sync::{AccessCheckError, AccessFlags, PipelineMemoryAccess, PipelineStages},
@ -350,7 +350,9 @@ where
// VUID-VkCommandBufferInheritanceRenderingInfo-multiview-06008 // VUID-VkCommandBufferInheritanceRenderingInfo-multiview-06008
if view_mask != 0 && !device.enabled_features().multiview { if view_mask != 0 && !device.enabled_features().multiview {
return Err(CommandBufferBeginError::RequirementNotMet { return Err(CommandBufferBeginError::RequirementNotMet {
required_for: "`inheritance_info.render_pass` is `CommandBufferInheritanceRenderPassType::BeginRendering`, where `view_mask` is not `0`", required_for: "`inheritance_info.render_pass` is \
`CommandBufferInheritanceRenderPassType::BeginRendering`, \
where `view_mask` is not `0`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["multiview"], features: &["multiview"],
..Default::default() ..Default::default()
@ -382,7 +384,7 @@ where
// Use unchecked, because all validation has been done above. // Use unchecked, because all validation has been done above.
if !unsafe { physical_device.format_properties_unchecked(format) } if !unsafe { physical_device.format_properties_unchecked(format) }
.potential_format_features() .potential_format_features()
.color_attachment .intersects(FormatFeatures::COLOR_ATTACHMENT)
{ {
return Err( return Err(
CommandBufferBeginError::ColorAttachmentFormatUsageNotSupported { CommandBufferBeginError::ColorAttachmentFormatUsageNotSupported {
@ -397,7 +399,7 @@ where
format.validate_device(device)?; format.validate_device(device)?;
// VUID-VkCommandBufferInheritanceRenderingInfo-depthAttachmentFormat-06540 // VUID-VkCommandBufferInheritanceRenderingInfo-depthAttachmentFormat-06540
if !format.aspects().depth { if !format.aspects().intersects(ImageAspects::DEPTH) {
return Err( return Err(
CommandBufferBeginError::DepthAttachmentFormatUsageNotSupported, CommandBufferBeginError::DepthAttachmentFormatUsageNotSupported,
); );
@ -407,7 +409,7 @@ where
// Use unchecked, because all validation has been done above. // Use unchecked, because all validation has been done above.
if !unsafe { physical_device.format_properties_unchecked(format) } if !unsafe { physical_device.format_properties_unchecked(format) }
.potential_format_features() .potential_format_features()
.depth_stencil_attachment .intersects(FormatFeatures::DEPTH_STENCIL_ATTACHMENT)
{ {
return Err( return Err(
CommandBufferBeginError::DepthAttachmentFormatUsageNotSupported, CommandBufferBeginError::DepthAttachmentFormatUsageNotSupported,
@ -420,7 +422,7 @@ where
format.validate_device(device)?; format.validate_device(device)?;
// VUID-VkCommandBufferInheritanceRenderingInfo-stencilAttachmentFormat-06541 // VUID-VkCommandBufferInheritanceRenderingInfo-stencilAttachmentFormat-06541
if !format.aspects().stencil { if !format.aspects().intersects(ImageAspects::STENCIL) {
return Err( return Err(
CommandBufferBeginError::StencilAttachmentFormatUsageNotSupported, CommandBufferBeginError::StencilAttachmentFormatUsageNotSupported,
); );
@ -430,7 +432,7 @@ where
// Use unchecked, because all validation has been done above. // Use unchecked, because all validation has been done above.
if !unsafe { physical_device.format_properties_unchecked(format) } if !unsafe { physical_device.format_properties_unchecked(format) }
.potential_format_features() .potential_format_features()
.depth_stencil_attachment .intersects(FormatFeatures::DEPTH_STENCIL_ATTACHMENT)
{ {
return Err( return Err(
CommandBufferBeginError::StencilAttachmentFormatUsageNotSupported, CommandBufferBeginError::StencilAttachmentFormatUsageNotSupported,
@ -472,10 +474,13 @@ where
} }
// VUID-vkBeginCommandBuffer-commandBuffer-00052 // VUID-vkBeginCommandBuffer-commandBuffer-00052
if control_flags.precise && !device.enabled_features().occlusion_query_precise { if control_flags.intersects(QueryControlFlags::PRECISE)
&& !device.enabled_features().occlusion_query_precise
{
return Err(CommandBufferBeginError::RequirementNotMet { return Err(CommandBufferBeginError::RequirementNotMet {
required_for: required_for: "`inheritance_info.occlusion_query` is \
"`inheritance_info.occlusion_query` is `Some(control_flags)`, where `control_flags.precise` is set", `Some(control_flags)`, where `control_flags` contains \
`QueryControlFlags::PRECISE`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["occlusion_query_precise"], features: &["occlusion_query_precise"],
..Default::default() ..Default::default()
@ -948,10 +953,7 @@ mod tests {
let source = CpuAccessibleBuffer::from_iter( let source = CpuAccessibleBuffer::from_iter(
&memory_allocator, &memory_allocator,
BufferUsage { BufferUsage::TRANSFER_SRC,
transfer_src: true,
..BufferUsage::empty()
},
true, true,
[1_u32, 2].iter().copied(), [1_u32, 2].iter().copied(),
) )
@ -959,10 +961,7 @@ mod tests {
let destination = CpuAccessibleBuffer::from_iter( let destination = CpuAccessibleBuffer::from_iter(
&memory_allocator, &memory_allocator,
BufferUsage { BufferUsage::TRANSFER_DST,
transfer_dst: true,
..BufferUsage::empty()
},
true, true,
[0_u32, 10, 20, 3, 4].iter().copied(), [0_u32, 10, 20, 3, 4].iter().copied(),
) )
@ -1083,11 +1082,7 @@ mod tests {
let memory_allocator = StandardMemoryAllocator::new_default(device.clone()); let memory_allocator = StandardMemoryAllocator::new_default(device.clone());
let source = CpuAccessibleBuffer::from_iter( let source = CpuAccessibleBuffer::from_iter(
&memory_allocator, &memory_allocator,
BufferUsage { BufferUsage::TRANSFER_SRC | BufferUsage::TRANSFER_DST,
transfer_src: true,
transfer_dst: true,
..BufferUsage::empty()
},
true, true,
[0_u32, 1, 2, 3].iter().copied(), [0_u32, 1, 2, 3].iter().copied(),
) )
@ -1135,11 +1130,7 @@ mod tests {
let memory_allocator = StandardMemoryAllocator::new_default(device.clone()); let memory_allocator = StandardMemoryAllocator::new_default(device.clone());
let source = CpuAccessibleBuffer::from_iter( let source = CpuAccessibleBuffer::from_iter(
&memory_allocator, &memory_allocator,
BufferUsage { BufferUsage::TRANSFER_SRC | BufferUsage::TRANSFER_DST,
transfer_src: true,
transfer_dst: true,
..BufferUsage::empty()
},
true, true,
[0_u32, 1, 2, 3].iter().copied(), [0_u32, 1, 2, 3].iter().copied(),
) )

View File

@ -8,7 +8,7 @@
// according to those terms. // according to those terms.
use crate::{ use crate::{
buffer::{BufferAccess, BufferContents, TypedBufferAccess}, buffer::{BufferAccess, BufferContents, BufferUsage, TypedBufferAccess},
command_buffer::{ command_buffer::{
allocator::CommandBufferAllocator, allocator::CommandBufferAllocator,
auto::RenderPassStateType, auto::RenderPassStateType,
@ -21,7 +21,7 @@ use crate::{
DescriptorSetUpdateError, DescriptorSetWithOffsets, DescriptorSetsCollection, DescriptorSetUpdateError, DescriptorSetWithOffsets, DescriptorSetsCollection,
DescriptorWriteInfo, WriteDescriptorSet, DescriptorWriteInfo, WriteDescriptorSet,
}, },
device::DeviceOwned, device::{DeviceOwned, QueueFlags},
pipeline::{ pipeline::{
graphics::{ graphics::{
input_assembly::{Index, IndexType}, input_assembly::{Index, IndexType},
@ -104,12 +104,18 @@ where
// VUID-vkCmdBindDescriptorSets-pipelineBindPoint-00361 // VUID-vkCmdBindDescriptorSets-pipelineBindPoint-00361
match pipeline_bind_point { match pipeline_bind_point {
PipelineBindPoint::Compute => { PipelineBindPoint::Compute => {
if !queue_family_properties.queue_flags.compute { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::COMPUTE)
{
return Err(BindPushError::NotSupportedByQueueFamily); return Err(BindPushError::NotSupportedByQueueFamily);
} }
} }
PipelineBindPoint::Graphics => { PipelineBindPoint::Graphics => {
if !queue_family_properties.queue_flags.graphics { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS)
{
return Err(BindPushError::NotSupportedByQueueFamily); return Err(BindPushError::NotSupportedByQueueFamily);
} }
} }
@ -152,11 +158,12 @@ where
/// ///
/// - Panics if the queue family of the command buffer does not support graphics operations. /// - Panics if the queue family of the command buffer does not support graphics operations.
/// - Panics if `self` and `index_buffer` do not belong to the same device. /// - Panics if `self` and `index_buffer` do not belong to the same device.
/// - Panics if `index_buffer` does not have the /// - Panics if `index_buffer` does not have the [`BufferUsage::INDEX_BUFFER`] usage enabled.
/// [`index_buffer`](crate::buffer::BufferUsage::index_buffer) usage enabled. /// - If the index buffer contains `u8` indices, panics if the [`index_type_uint8`] feature is
/// - If the index buffer contains `u8` indices, panics if the /// not enabled on the device.
/// [`index_type_uint8`](crate::device::Features::index_type_uint8) feature is not ///
/// enabled on the device. /// [`BufferUsage::INDEX_BUFFER`]: crate::buffer::BufferUsage::INDEX_BUFFER
/// [`index_type_uint8`]: crate::device::Features::index_type_uint8
pub fn bind_index_buffer<Ib, I>(&mut self, index_buffer: Arc<Ib>) -> &mut Self pub fn bind_index_buffer<Ib, I>(&mut self, index_buffer: Arc<Ib>) -> &mut Self
where where
Ib: TypedBufferAccess<Content = [I]> + 'static, Ib: TypedBufferAccess<Content = [I]> + 'static,
@ -180,7 +187,10 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdBindIndexBuffer-commandBuffer-cmdpool // VUID-vkCmdBindIndexBuffer-commandBuffer-cmdpool
if !queue_family_properties.queue_flags.graphics { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS)
{
return Err(BindPushError::NotSupportedByQueueFamily); return Err(BindPushError::NotSupportedByQueueFamily);
} }
@ -188,7 +198,7 @@ where
assert_eq!(self.device(), index_buffer.device()); assert_eq!(self.device(), index_buffer.device());
// VUID-vkCmdBindIndexBuffer-buffer-00433 // VUID-vkCmdBindIndexBuffer-buffer-00433
if !index_buffer.usage().index_buffer { if !index_buffer.usage().intersects(BufferUsage::INDEX_BUFFER) {
return Err(BindPushError::IndexBufferMissingUsage); return Err(BindPushError::IndexBufferMissingUsage);
} }
@ -232,7 +242,10 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdBindPipeline-pipelineBindPoint-00777 // VUID-vkCmdBindPipeline-pipelineBindPoint-00777
if !queue_family_properties.queue_flags.compute { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::COMPUTE)
{
return Err(BindPushError::NotSupportedByQueueFamily); return Err(BindPushError::NotSupportedByQueueFamily);
} }
@ -265,7 +278,10 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdBindPipeline-pipelineBindPoint-00778 // VUID-vkCmdBindPipeline-pipelineBindPoint-00778
if !queue_family_properties.queue_flags.graphics { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS)
{
return Err(BindPushError::NotSupportedByQueueFamily); return Err(BindPushError::NotSupportedByQueueFamily);
} }
@ -322,11 +338,13 @@ where
/// ///
/// - Panics if the queue family of the command buffer does not support graphics operations. /// - Panics if the queue family of the command buffer does not support graphics operations.
/// - Panics if the highest vertex buffer binding being bound is greater than the /// - Panics if the highest vertex buffer binding being bound is greater than the
/// [`max_vertex_input_bindings`](crate::device::Properties::max_vertex_input_bindings) /// [`max_vertex_input_bindings`] device property.
// device property.
/// - Panics if `self` and any element of `vertex_buffers` do not belong to the same device. /// - Panics if `self` and any element of `vertex_buffers` do not belong to the same device.
/// - Panics if any element of `vertex_buffers` does not have the /// - Panics if any element of `vertex_buffers` does not have the
/// [`vertex_buffer`](crate::buffer::BufferUsage::vertex_buffer) usage enabled. /// [`BufferUsage::VERTEX_BUFFER`] usage enabled.
///
/// [`max_vertex_input_bindings`]: crate::device::Properties::max_vertex_input_bindings
/// [`BufferUsage::VERTEX_BUFFER`]: crate::buffer::BufferUsage::VERTEX_BUFFER
pub fn bind_vertex_buffers( pub fn bind_vertex_buffers(
&mut self, &mut self,
first_binding: u32, first_binding: u32,
@ -355,7 +373,10 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdBindVertexBuffers-commandBuffer-cmdpool // VUID-vkCmdBindVertexBuffers-commandBuffer-cmdpool
if !queue_family_properties.queue_flags.graphics { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS)
{
return Err(BindPushError::NotSupportedByQueueFamily); return Err(BindPushError::NotSupportedByQueueFamily);
} }
@ -383,7 +404,7 @@ where
assert_eq!(self.device(), buffer.device()); assert_eq!(self.device(), buffer.device());
// VUID-vkCmdBindVertexBuffers-pBuffers-00627 // VUID-vkCmdBindVertexBuffers-pBuffers-00627
if !buffer.usage().vertex_buffer { if !buffer.usage().intersects(BufferUsage::VERTEX_BUFFER) {
return Err(BindPushError::VertexBufferMissingUsage); return Err(BindPushError::VertexBufferMissingUsage);
} }
} }
@ -554,7 +575,7 @@ where
) -> Result<(), BindPushError> { ) -> Result<(), BindPushError> {
if !self.device().enabled_extensions().khr_push_descriptor { if !self.device().enabled_extensions().khr_push_descriptor {
return Err(BindPushError::RequirementNotMet { return Err(BindPushError::RequirementNotMet {
required_for: "`push_descriptor_set`", required_for: "`AutoCommandBufferBuilder::push_descriptor_set`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
device_extensions: &["khr_push_descriptor"], device_extensions: &["khr_push_descriptor"],
..Default::default() ..Default::default()
@ -571,12 +592,18 @@ where
// VUID-vkCmdPushDescriptorSetKHR-pipelineBindPoint-00363 // VUID-vkCmdPushDescriptorSetKHR-pipelineBindPoint-00363
match pipeline_bind_point { match pipeline_bind_point {
PipelineBindPoint::Compute => { PipelineBindPoint::Compute => {
if !queue_family_properties.queue_flags.compute { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::COMPUTE)
{
return Err(BindPushError::NotSupportedByQueueFamily); return Err(BindPushError::NotSupportedByQueueFamily);
} }
} }
PipelineBindPoint::Graphics => { PipelineBindPoint::Graphics => {
if !queue_family_properties.queue_flags.graphics { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS)
{
return Err(BindPushError::NotSupportedByQueueFamily); return Err(BindPushError::NotSupportedByQueueFamily);
} }
} }
@ -999,7 +1026,7 @@ impl UnsafeCommandBufferBuilder {
let inner = buffer.inner(); let inner = buffer.inner();
debug_assert!(inner.offset < inner.buffer.size()); debug_assert!(inner.offset < inner.buffer.size());
debug_assert!(inner.buffer.usage().index_buffer); debug_assert!(inner.buffer.usage().intersects(BufferUsage::INDEX_BUFFER));
(fns.v1_0.cmd_bind_index_buffer)( (fns.v1_0.cmd_bind_index_buffer)(
self.handle, self.handle,
@ -1184,7 +1211,7 @@ impl UnsafeCommandBufferBuilderBindVertexBuffer {
#[inline] #[inline]
pub fn add(&mut self, buffer: &dyn BufferAccess) { pub fn add(&mut self, buffer: &dyn BufferAccess) {
let inner = buffer.inner(); let inner = buffer.inner();
debug_assert!(inner.buffer.usage().vertex_buffer); debug_assert!(inner.buffer.usage().intersects(BufferUsage::VERTEX_BUFFER));
self.raw_buffers.push(inner.buffer.handle()); self.raw_buffers.push(inner.buffer.handle());
self.offsets.push(inner.offset); self.offsets.push(inner.offset);
} }

View File

@ -14,7 +14,7 @@ use crate::{
sys::UnsafeCommandBufferBuilder, sys::UnsafeCommandBufferBuilder,
AutoCommandBufferBuilder, AutoCommandBufferBuilder,
}, },
device::DeviceOwned, device::{DeviceOwned, QueueFlags},
instance::debug::DebugUtilsLabel, instance::debug::DebugUtilsLabel,
RequiresOneOf, RequiresOneOf,
}; };
@ -26,9 +26,9 @@ use std::{
/// # Commands for debugging. /// # Commands for debugging.
/// ///
/// These commands all require the /// These commands all require the [`ext_debug_utils`] extension to be enabled on the instance.
/// [`ext_debug_utils`](crate::instance::InstanceExtensions::ext_debug_utils) to be enabled on the ///
/// instance. /// [`ext_debug_utils`]: crate::instance::InstanceExtensions::ext_debug_utils
impl<L, A> AutoCommandBufferBuilder<L, A> impl<L, A> AutoCommandBufferBuilder<L, A>
where where
A: CommandBufferAllocator, A: CommandBufferAllocator,
@ -58,7 +58,7 @@ where
.ext_debug_utils .ext_debug_utils
{ {
return Err(DebugUtilsError::RequirementNotMet { return Err(DebugUtilsError::RequirementNotMet {
required_for: "`begin_debug_utils_label`", required_for: "`AutoCommandBufferBuilder::begin_debug_utils_label`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
instance_extensions: &["ext_debug_utils"], instance_extensions: &["ext_debug_utils"],
..Default::default() ..Default::default()
@ -69,8 +69,9 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdBeginDebugUtilsLabelEXT-commandBuffer-cmdpool // VUID-vkCmdBeginDebugUtilsLabelEXT-commandBuffer-cmdpool
if !(queue_family_properties.queue_flags.graphics if !queue_family_properties
|| queue_family_properties.queue_flags.compute) .queue_flags
.intersects(QueueFlags::GRAPHICS | QueueFlags::COMPUTE)
{ {
return Err(DebugUtilsError::NotSupportedByQueueFamily); return Err(DebugUtilsError::NotSupportedByQueueFamily);
} }
@ -101,7 +102,7 @@ where
.ext_debug_utils .ext_debug_utils
{ {
return Err(DebugUtilsError::RequirementNotMet { return Err(DebugUtilsError::RequirementNotMet {
required_for: "`end_debug_utils_label`", required_for: "`AutoCommandBufferBuilder::end_debug_utils_label`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
instance_extensions: &["ext_debug_utils"], instance_extensions: &["ext_debug_utils"],
..Default::default() ..Default::default()
@ -112,8 +113,9 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdEndDebugUtilsLabelEXT-commandBuffer-cmdpool // VUID-vkCmdEndDebugUtilsLabelEXT-commandBuffer-cmdpool
if !(queue_family_properties.queue_flags.graphics if !queue_family_properties
|| queue_family_properties.queue_flags.compute) .queue_flags
.intersects(QueueFlags::GRAPHICS | QueueFlags::COMPUTE)
{ {
return Err(DebugUtilsError::NotSupportedByQueueFamily); return Err(DebugUtilsError::NotSupportedByQueueFamily);
} }
@ -152,7 +154,7 @@ where
.ext_debug_utils .ext_debug_utils
{ {
return Err(DebugUtilsError::RequirementNotMet { return Err(DebugUtilsError::RequirementNotMet {
required_for: "`insert_debug_utils_label`", required_for: "`AutoCommandBufferBuilder::insert_debug_utils_label`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
instance_extensions: &["ext_debug_utils"], instance_extensions: &["ext_debug_utils"],
..Default::default() ..Default::default()
@ -163,8 +165,9 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdInsertDebugUtilsLabelEXT-commandBuffer-cmdpool // VUID-vkCmdInsertDebugUtilsLabelEXT-commandBuffer-cmdpool
if !(queue_family_properties.queue_flags.graphics if !queue_family_properties
|| queue_family_properties.queue_flags.compute) .queue_flags
.intersects(QueueFlags::GRAPHICS | QueueFlags::COMPUTE)
{ {
return Err(DebugUtilsError::NotSupportedByQueueFamily); return Err(DebugUtilsError::NotSupportedByQueueFamily);
} }

View File

@ -14,7 +14,7 @@ use crate::{
sys::UnsafeCommandBufferBuilder, sys::UnsafeCommandBufferBuilder,
AutoCommandBufferBuilder, AutoCommandBufferBuilder,
}, },
device::DeviceOwned, device::{DeviceOwned, QueueFlags},
pipeline::{ pipeline::{
graphics::{ graphics::{
color_blend::LogicOp, color_blend::LogicOp,
@ -82,7 +82,10 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdSetBlendConstants-commandBuffer-cmdpool // VUID-vkCmdSetBlendConstants-commandBuffer-cmdpool
if !queue_family_properties.queue_flags.graphics { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS)
{
return Err(SetDynamicStateError::NotSupportedByQueueFamily); return Err(SetDynamicStateError::NotSupportedByQueueFamily);
} }
@ -125,14 +128,17 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdSetColorWriteEnableEXT-commandBuffer-cmdpool // VUID-vkCmdSetColorWriteEnableEXT-commandBuffer-cmdpool
if !queue_family_properties.queue_flags.graphics { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS)
{
return Err(SetDynamicStateError::NotSupportedByQueueFamily); return Err(SetDynamicStateError::NotSupportedByQueueFamily);
} }
// VUID-vkCmdSetColorWriteEnableEXT-None-04803 // VUID-vkCmdSetColorWriteEnableEXT-None-04803
if !self.device().enabled_features().color_write_enable { if !self.device().enabled_features().color_write_enable {
return Err(SetDynamicStateError::RequirementNotMet { return Err(SetDynamicStateError::RequirementNotMet {
required_for: "`set_color_write_enable`", required_for: "`AutoCommandBufferBuilder::set_color_write_enable`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
device_extensions: &["ext_color_write_enable"], device_extensions: &["ext_color_write_enable"],
..Default::default() ..Default::default()
@ -188,7 +194,10 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdSetCullMode-commandBuffer-cmdpool // VUID-vkCmdSetCullMode-commandBuffer-cmdpool
if !queue_family_properties.queue_flags.graphics { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS)
{
return Err(SetDynamicStateError::NotSupportedByQueueFamily); return Err(SetDynamicStateError::NotSupportedByQueueFamily);
} }
@ -197,7 +206,7 @@ where
|| self.device().enabled_features().extended_dynamic_state) || self.device().enabled_features().extended_dynamic_state)
{ {
return Err(SetDynamicStateError::RequirementNotMet { return Err(SetDynamicStateError::RequirementNotMet {
required_for: "`set_cull_mode`", required_for: "`AutoCommandBufferBuilder::set_cull_mode`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
api_version: Some(Version::V1_3), api_version: Some(Version::V1_3),
features: &["extended_dynamic_state"], features: &["extended_dynamic_state"],
@ -245,7 +254,10 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdSetDepthBias-commandBuffer-cmdpool // VUID-vkCmdSetDepthBias-commandBuffer-cmdpool
if !queue_family_properties.queue_flags.graphics { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS)
{
return Err(SetDynamicStateError::NotSupportedByQueueFamily); return Err(SetDynamicStateError::NotSupportedByQueueFamily);
} }
@ -288,7 +300,10 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdSetDepthBiasEnable-commandBuffer-cmdpool // VUID-vkCmdSetDepthBiasEnable-commandBuffer-cmdpool
if !queue_family_properties.queue_flags.graphics { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS)
{
return Err(SetDynamicStateError::NotSupportedByQueueFamily); return Err(SetDynamicStateError::NotSupportedByQueueFamily);
} }
@ -297,7 +312,7 @@ where
|| self.device().enabled_features().extended_dynamic_state2) || self.device().enabled_features().extended_dynamic_state2)
{ {
return Err(SetDynamicStateError::RequirementNotMet { return Err(SetDynamicStateError::RequirementNotMet {
required_for: "`set_depth_bias_enable`", required_for: "`AutoCommandBufferBuilder::set_depth_bias_enable`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
api_version: Some(Version::V1_3), api_version: Some(Version::V1_3),
features: &["extended_dynamic_state2"], features: &["extended_dynamic_state2"],
@ -338,7 +353,10 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdSetDepthBounds-commandBuffer-cmdpool // VUID-vkCmdSetDepthBounds-commandBuffer-cmdpool
if !queue_family_properties.queue_flags.graphics { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS)
{
return Err(SetDynamicStateError::NotSupportedByQueueFamily); return Err(SetDynamicStateError::NotSupportedByQueueFamily);
} }
@ -390,7 +408,10 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdSetDepthBoundsTestEnable-commandBuffer-cmdpool // VUID-vkCmdSetDepthBoundsTestEnable-commandBuffer-cmdpool
if !queue_family_properties.queue_flags.graphics { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS)
{
return Err(SetDynamicStateError::NotSupportedByQueueFamily); return Err(SetDynamicStateError::NotSupportedByQueueFamily);
} }
@ -399,7 +420,7 @@ where
|| self.device().enabled_features().extended_dynamic_state) || self.device().enabled_features().extended_dynamic_state)
{ {
return Err(SetDynamicStateError::RequirementNotMet { return Err(SetDynamicStateError::RequirementNotMet {
required_for: "`set_depth_bounds_test_enable`", required_for: "`AutoCommandBufferBuilder::set_depth_bounds_test_enable`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
api_version: Some(Version::V1_3), api_version: Some(Version::V1_3),
features: &["extended_dynamic_state"], features: &["extended_dynamic_state"],
@ -442,7 +463,10 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdSetDepthCompareOp-commandBuffer-cmdpool // VUID-vkCmdSetDepthCompareOp-commandBuffer-cmdpool
if !queue_family_properties.queue_flags.graphics { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS)
{
return Err(SetDynamicStateError::NotSupportedByQueueFamily); return Err(SetDynamicStateError::NotSupportedByQueueFamily);
} }
@ -451,7 +475,7 @@ where
|| self.device().enabled_features().extended_dynamic_state) || self.device().enabled_features().extended_dynamic_state)
{ {
return Err(SetDynamicStateError::RequirementNotMet { return Err(SetDynamicStateError::RequirementNotMet {
required_for: "`set_depth_compare_op`", required_for: "`AutoCommandBufferBuilder::set_depth_compare_op`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
api_version: Some(Version::V1_3), api_version: Some(Version::V1_3),
features: &["extended_dynamic_state"], features: &["extended_dynamic_state"],
@ -488,7 +512,10 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdSetDepthTestEnable-commandBuffer-cmdpool // VUID-vkCmdSetDepthTestEnable-commandBuffer-cmdpool
if !queue_family_properties.queue_flags.graphics { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS)
{
return Err(SetDynamicStateError::NotSupportedByQueueFamily); return Err(SetDynamicStateError::NotSupportedByQueueFamily);
} }
@ -497,7 +524,7 @@ where
|| self.device().enabled_features().extended_dynamic_state) || self.device().enabled_features().extended_dynamic_state)
{ {
return Err(SetDynamicStateError::RequirementNotMet { return Err(SetDynamicStateError::RequirementNotMet {
required_for: "`set_depth_test_enable`", required_for: "`AutoCommandBufferBuilder::set_depth_test_enable`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
api_version: Some(Version::V1_3), api_version: Some(Version::V1_3),
features: &["extended_dynamic_state"], features: &["extended_dynamic_state"],
@ -534,7 +561,10 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdSetDepthWriteEnable-commandBuffer-cmdpool // VUID-vkCmdSetDepthWriteEnable-commandBuffer-cmdpool
if !queue_family_properties.queue_flags.graphics { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS)
{
return Err(SetDynamicStateError::NotSupportedByQueueFamily); return Err(SetDynamicStateError::NotSupportedByQueueFamily);
} }
@ -543,7 +573,7 @@ where
|| self.device().enabled_features().extended_dynamic_state) || self.device().enabled_features().extended_dynamic_state)
{ {
return Err(SetDynamicStateError::RequirementNotMet { return Err(SetDynamicStateError::RequirementNotMet {
required_for: "`set_depth_write_enable`", required_for: "`AutoCommandBufferBuilder::set_depth_write_enable`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
api_version: Some(Version::V1_3), api_version: Some(Version::V1_3),
features: &["extended_dynamic_state"], features: &["extended_dynamic_state"],
@ -594,13 +624,16 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdSetDiscardRectangle-commandBuffer-cmdpool // VUID-vkCmdSetDiscardRectangle-commandBuffer-cmdpool
if !queue_family_properties.queue_flags.graphics { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS)
{
return Err(SetDynamicStateError::NotSupportedByQueueFamily); return Err(SetDynamicStateError::NotSupportedByQueueFamily);
} }
if self.device().enabled_extensions().ext_discard_rectangles { if self.device().enabled_extensions().ext_discard_rectangles {
return Err(SetDynamicStateError::RequirementNotMet { return Err(SetDynamicStateError::RequirementNotMet {
required_for: "`set_discard_rectangle`", required_for: "`AutoCommandBufferBuilder::set_discard_rectangle`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
device_extensions: &["ext_discard_rectangles"], device_extensions: &["ext_discard_rectangles"],
..Default::default() ..Default::default()
@ -659,7 +692,10 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdSetFrontFace-commandBuffer-cmdpool // VUID-vkCmdSetFrontFace-commandBuffer-cmdpool
if !queue_family_properties.queue_flags.graphics { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS)
{
return Err(SetDynamicStateError::NotSupportedByQueueFamily); return Err(SetDynamicStateError::NotSupportedByQueueFamily);
} }
@ -668,7 +704,7 @@ where
|| self.device().enabled_features().extended_dynamic_state) || self.device().enabled_features().extended_dynamic_state)
{ {
return Err(SetDynamicStateError::RequirementNotMet { return Err(SetDynamicStateError::RequirementNotMet {
required_for: "`set_front_face`", required_for: "`AutoCommandBufferBuilder::set_front_face`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
api_version: Some(Version::V1_3), api_version: Some(Version::V1_3),
features: &["extended_dynamic_state"], features: &["extended_dynamic_state"],
@ -709,13 +745,16 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdSetLineStippleEXT-commandBuffer-cmdpool // VUID-vkCmdSetLineStippleEXT-commandBuffer-cmdpool
if !queue_family_properties.queue_flags.graphics { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS)
{
return Err(SetDynamicStateError::NotSupportedByQueueFamily); return Err(SetDynamicStateError::NotSupportedByQueueFamily);
} }
if !self.device().enabled_extensions().ext_line_rasterization { if !self.device().enabled_extensions().ext_line_rasterization {
return Err(SetDynamicStateError::RequirementNotMet { return Err(SetDynamicStateError::RequirementNotMet {
required_for: "`set_line_stipple`", required_for: "`AutoCommandBufferBuilder::set_line_stipple`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
device_extensions: &["ext_line_rasterization"], device_extensions: &["ext_line_rasterization"],
..Default::default() ..Default::default()
@ -755,7 +794,10 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdSetLineWidth-commandBuffer-cmdpool // VUID-vkCmdSetLineWidth-commandBuffer-cmdpool
if !queue_family_properties.queue_flags.graphics { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS)
{
return Err(SetDynamicStateError::NotSupportedByQueueFamily); return Err(SetDynamicStateError::NotSupportedByQueueFamily);
} }
@ -801,7 +843,10 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdSetLogicOpEXT-commandBuffer-cmdpool // VUID-vkCmdSetLogicOpEXT-commandBuffer-cmdpool
if !queue_family_properties.queue_flags.graphics { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS)
{
return Err(SetDynamicStateError::NotSupportedByQueueFamily); return Err(SetDynamicStateError::NotSupportedByQueueFamily);
} }
@ -812,7 +857,7 @@ where
.extended_dynamic_state2_logic_op .extended_dynamic_state2_logic_op
{ {
return Err(SetDynamicStateError::RequirementNotMet { return Err(SetDynamicStateError::RequirementNotMet {
required_for: "`set_logic_op`", required_for: "`AutoCommandBufferBuilder::set_logic_op`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["extended_dynamic_state2_logic_op"], features: &["extended_dynamic_state2_logic_op"],
..Default::default() ..Default::default()
@ -852,7 +897,10 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdSetPatchControlPointsEXT-commandBuffer-cmdpool // VUID-vkCmdSetPatchControlPointsEXT-commandBuffer-cmdpool
if !queue_family_properties.queue_flags.graphics { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS)
{
return Err(SetDynamicStateError::NotSupportedByQueueFamily); return Err(SetDynamicStateError::NotSupportedByQueueFamily);
} }
@ -863,7 +911,7 @@ where
.extended_dynamic_state2_patch_control_points .extended_dynamic_state2_patch_control_points
{ {
return Err(SetDynamicStateError::RequirementNotMet { return Err(SetDynamicStateError::RequirementNotMet {
required_for: "`set_patch_control_points`", required_for: "`AutoCommandBufferBuilder::set_patch_control_points`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["extended_dynamic_state2_patch_control_points"], features: &["extended_dynamic_state2_patch_control_points"],
..Default::default() ..Default::default()
@ -923,7 +971,10 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdSetPrimitiveRestartEnable-commandBuffer-cmdpool // VUID-vkCmdSetPrimitiveRestartEnable-commandBuffer-cmdpool
if !queue_family_properties.queue_flags.graphics { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS)
{
return Err(SetDynamicStateError::NotSupportedByQueueFamily); return Err(SetDynamicStateError::NotSupportedByQueueFamily);
} }
@ -932,7 +983,7 @@ where
|| self.device().enabled_features().extended_dynamic_state2) || self.device().enabled_features().extended_dynamic_state2)
{ {
return Err(SetDynamicStateError::RequirementNotMet { return Err(SetDynamicStateError::RequirementNotMet {
required_for: "`set_primitive_restart_enable`", required_for: "`AutoCommandBufferBuilder::set_primitive_restart_enable`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
api_version: Some(Version::V1_3), api_version: Some(Version::V1_3),
features: &["extended_dynamic_state2"], features: &["extended_dynamic_state2"],
@ -979,7 +1030,10 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdSetPrimitiveTopology-commandBuffer-cmdpool // VUID-vkCmdSetPrimitiveTopology-commandBuffer-cmdpool
if !queue_family_properties.queue_flags.graphics { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS)
{
return Err(SetDynamicStateError::NotSupportedByQueueFamily); return Err(SetDynamicStateError::NotSupportedByQueueFamily);
} }
@ -988,7 +1042,7 @@ where
|| self.device().enabled_features().extended_dynamic_state) || self.device().enabled_features().extended_dynamic_state)
{ {
return Err(SetDynamicStateError::RequirementNotMet { return Err(SetDynamicStateError::RequirementNotMet {
required_for: "`set_primitive_topology`", required_for: "`AutoCommandBufferBuilder::set_primitive_topology`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
api_version: Some(Version::V1_3), api_version: Some(Version::V1_3),
features: &["extended_dynamic_state"], features: &["extended_dynamic_state"],
@ -1006,9 +1060,8 @@ where
&& !self.device().enabled_features().triangle_fans && !self.device().enabled_features().triangle_fans
{ {
return Err(SetDynamicStateError::RequirementNotMet { return Err(SetDynamicStateError::RequirementNotMet {
required_for: required_for: "this device is a portability subset device, and `topology` \
"this device is a portability subset device, and `topology` is \ is `PrimitiveTopology::TriangleFan`",
`PrimitiveTopology::TriangleFan`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["triangle_fans"], features: &["triangle_fans"],
..Default::default() ..Default::default()
@ -1075,7 +1128,10 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdSetRasterizerDiscardEnable-commandBuffer-cmdpool // VUID-vkCmdSetRasterizerDiscardEnable-commandBuffer-cmdpool
if !queue_family_properties.queue_flags.graphics { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS)
{
return Err(SetDynamicStateError::NotSupportedByQueueFamily); return Err(SetDynamicStateError::NotSupportedByQueueFamily);
} }
@ -1084,7 +1140,7 @@ where
|| self.device().enabled_features().extended_dynamic_state2) || self.device().enabled_features().extended_dynamic_state2)
{ {
return Err(SetDynamicStateError::RequirementNotMet { return Err(SetDynamicStateError::RequirementNotMet {
required_for: "`set_rasterizer_discard_enable`", required_for: "`AutoCommandBufferBuilder::set_rasterizer_discard_enable`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
api_version: Some(Version::V1_3), api_version: Some(Version::V1_3),
features: &["extended_dynamic_state2"], features: &["extended_dynamic_state2"],
@ -1131,7 +1187,10 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdSetScissor-commandBuffer-cmdpool // VUID-vkCmdSetScissor-commandBuffer-cmdpool
if !queue_family_properties.queue_flags.graphics { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS)
{
return Err(SetDynamicStateError::NotSupportedByQueueFamily); return Err(SetDynamicStateError::NotSupportedByQueueFamily);
} }
@ -1208,7 +1267,10 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdSetScissorWithCount-commandBuffer-cmdpool // VUID-vkCmdSetScissorWithCount-commandBuffer-cmdpool
if !queue_family_properties.queue_flags.graphics { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS)
{
return Err(SetDynamicStateError::NotSupportedByQueueFamily); return Err(SetDynamicStateError::NotSupportedByQueueFamily);
} }
@ -1217,7 +1279,7 @@ where
|| self.device().enabled_features().extended_dynamic_state) || self.device().enabled_features().extended_dynamic_state)
{ {
return Err(SetDynamicStateError::RequirementNotMet { return Err(SetDynamicStateError::RequirementNotMet {
required_for: "`set_scissor_with_count`", required_for: "`AutoCommandBufferBuilder::set_scissor_with_count`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
api_version: Some(Version::V1_3), api_version: Some(Version::V1_3),
features: &["extended_dynamic_state"], features: &["extended_dynamic_state"],
@ -1282,7 +1344,10 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdSetStencilCompareMask-commandBuffer-cmdpool // VUID-vkCmdSetStencilCompareMask-commandBuffer-cmdpool
if !queue_family_properties.queue_flags.graphics { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS)
{
return Err(SetDynamicStateError::NotSupportedByQueueFamily); return Err(SetDynamicStateError::NotSupportedByQueueFamily);
} }
@ -1345,7 +1410,10 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdSetStencilOp-commandBuffer-cmdpool // VUID-vkCmdSetStencilOp-commandBuffer-cmdpool
if !queue_family_properties.queue_flags.graphics { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS)
{
return Err(SetDynamicStateError::NotSupportedByQueueFamily); return Err(SetDynamicStateError::NotSupportedByQueueFamily);
} }
@ -1354,7 +1422,7 @@ where
|| self.device().enabled_features().extended_dynamic_state) || self.device().enabled_features().extended_dynamic_state)
{ {
return Err(SetDynamicStateError::RequirementNotMet { return Err(SetDynamicStateError::RequirementNotMet {
required_for: "`set_stencil_op`", required_for: "`AutoCommandBufferBuilder::set_stencil_op`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
api_version: Some(Version::V1_3), api_version: Some(Version::V1_3),
features: &["extended_dynamic_state"], features: &["extended_dynamic_state"],
@ -1396,7 +1464,10 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdSetStencilReference-commandBuffer-cmdpool // VUID-vkCmdSetStencilReference-commandBuffer-cmdpool
if !queue_family_properties.queue_flags.graphics { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS)
{
return Err(SetDynamicStateError::NotSupportedByQueueFamily); return Err(SetDynamicStateError::NotSupportedByQueueFamily);
} }
@ -1428,7 +1499,10 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdSetStencilTestEnable-commandBuffer-cmdpool // VUID-vkCmdSetStencilTestEnable-commandBuffer-cmdpool
if !queue_family_properties.queue_flags.graphics { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS)
{
return Err(SetDynamicStateError::NotSupportedByQueueFamily); return Err(SetDynamicStateError::NotSupportedByQueueFamily);
} }
@ -1437,7 +1511,7 @@ where
|| self.device().enabled_features().extended_dynamic_state) || self.device().enabled_features().extended_dynamic_state)
{ {
return Err(SetDynamicStateError::RequirementNotMet { return Err(SetDynamicStateError::RequirementNotMet {
required_for: "`set_stencil_test_enable`", required_for: "`AutoCommandBufferBuilder::set_stencil_test_enable`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
api_version: Some(Version::V1_3), api_version: Some(Version::V1_3),
features: &["extended_dynamic_state"], features: &["extended_dynamic_state"],
@ -1479,7 +1553,10 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdSetStencilWriteMask-commandBuffer-cmdpool // VUID-vkCmdSetStencilWriteMask-commandBuffer-cmdpool
if !queue_family_properties.queue_flags.graphics { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS)
{
return Err(SetDynamicStateError::NotSupportedByQueueFamily); return Err(SetDynamicStateError::NotSupportedByQueueFamily);
} }
@ -1522,7 +1599,10 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdSetViewport-commandBuffer-cmdpool // VUID-vkCmdSetViewport-commandBuffer-cmdpool
if !queue_family_properties.queue_flags.graphics { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS)
{
return Err(SetDynamicStateError::NotSupportedByQueueFamily); return Err(SetDynamicStateError::NotSupportedByQueueFamily);
} }
@ -1599,7 +1679,10 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdSetViewportWithCount-commandBuffer-cmdpool // VUID-vkCmdSetViewportWithCount-commandBuffer-cmdpool
if !queue_family_properties.queue_flags.graphics { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS)
{
return Err(SetDynamicStateError::NotSupportedByQueueFamily); return Err(SetDynamicStateError::NotSupportedByQueueFamily);
} }
@ -1608,7 +1691,7 @@ where
|| self.device().enabled_features().extended_dynamic_state) || self.device().enabled_features().extended_dynamic_state)
{ {
return Err(SetDynamicStateError::RequirementNotMet { return Err(SetDynamicStateError::RequirementNotMet {
required_for: "`set_viewport_with_count`", required_for: "`AutoCommandBufferBuilder::set_viewport_with_count`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
api_version: Some(Version::V1_3), api_version: Some(Version::V1_3),
features: &["extended_dynamic_state"], features: &["extended_dynamic_state"],

View File

@ -14,11 +14,11 @@ use crate::{
sys::UnsafeCommandBufferBuilder, sys::UnsafeCommandBufferBuilder,
AutoCommandBufferBuilder, CopyError, CopyErrorResource, AutoCommandBufferBuilder, CopyError, CopyErrorResource,
}, },
device::DeviceOwned, device::{DeviceOwned, QueueFlags},
format::{ClearColorValue, ClearDepthStencilValue, NumericType}, format::{ClearColorValue, ClearDepthStencilValue, FormatFeatures, NumericType},
image::{ image::{
ImageAccess, ImageAspects, ImageDimensions, ImageLayout, ImageSubresourceLayers, ImageAccess, ImageAspects, ImageDimensions, ImageLayout, ImageSubresourceLayers,
ImageSubresourceRange, ImageType, SampleCount, SampleCounts, ImageSubresourceRange, ImageType, ImageUsage, SampleCount, SampleCounts,
}, },
sampler::Filter, sampler::Filter,
sync::{AccessFlags, PipelineMemoryAccess, PipelineStages}, sync::{AccessFlags, PipelineMemoryAccess, PipelineStages},
@ -89,7 +89,10 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdBlitImage2-commandBuffer-cmdpool // VUID-vkCmdBlitImage2-commandBuffer-cmdpool
if !queue_family_properties.queue_flags.graphics { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS)
{
return Err(CopyError::NotSupportedByQueueFamily); return Err(CopyError::NotSupportedByQueueFamily);
} }
@ -125,7 +128,7 @@ where
let dst_image_type = dst_image.dimensions().image_type(); let dst_image_type = dst_image.dimensions().image_type();
// VUID-VkBlitImageInfo2-srcImage-00219 // VUID-VkBlitImageInfo2-srcImage-00219
if !src_image.usage().transfer_src { if !src_image.usage().intersects(ImageUsage::TRANSFER_SRC) {
return Err(CopyError::MissingUsage { return Err(CopyError::MissingUsage {
resource: CopyErrorResource::Source, resource: CopyErrorResource::Source,
usage: "transfer_src", usage: "transfer_src",
@ -133,7 +136,7 @@ where
} }
// VUID-VkBlitImageInfo2-dstImage-00224 // VUID-VkBlitImageInfo2-dstImage-00224
if !dst_image.usage().transfer_dst { if !dst_image.usage().intersects(ImageUsage::TRANSFER_DST) {
return Err(CopyError::MissingUsage { return Err(CopyError::MissingUsage {
resource: CopyErrorResource::Destination, resource: CopyErrorResource::Destination,
usage: "transfer_dst", usage: "transfer_dst",
@ -141,7 +144,10 @@ where
} }
// VUID-VkBlitImageInfo2-srcImage-01999 // VUID-VkBlitImageInfo2-srcImage-01999
if !src_image.format_features().blit_src { if !src_image
.format_features()
.intersects(FormatFeatures::BLIT_SRC)
{
return Err(CopyError::MissingFormatFeature { return Err(CopyError::MissingFormatFeature {
resource: CopyErrorResource::Source, resource: CopyErrorResource::Source,
format_feature: "blit_src", format_feature: "blit_src",
@ -149,7 +155,10 @@ where
} }
// VUID-VkBlitImageInfo2-dstImage-02000 // VUID-VkBlitImageInfo2-dstImage-02000
if !dst_image.format_features().blit_dst { if !dst_image
.format_features()
.intersects(FormatFeatures::BLIT_DST)
{
return Err(CopyError::MissingFormatFeature { return Err(CopyError::MissingFormatFeature {
resource: CopyErrorResource::Destination, resource: CopyErrorResource::Destination,
format_feature: "blit_dst", format_feature: "blit_dst",
@ -172,7 +181,9 @@ where
}); });
} }
if !(src_image_aspects.color && dst_image_aspects.color) { if !(src_image_aspects.intersects(ImageAspects::COLOR)
&& dst_image_aspects.intersects(ImageAspects::COLOR))
{
// VUID-VkBlitImageInfo2-srcImage-00231 // VUID-VkBlitImageInfo2-srcImage-00231
if src_image.format() != dst_image.format() { if src_image.format() != dst_image.format() {
return Err(CopyError::FormatsMismatch { return Err(CopyError::FormatsMismatch {
@ -218,10 +229,7 @@ where
return Err(CopyError::SampleCountInvalid { return Err(CopyError::SampleCountInvalid {
resource: CopyErrorResource::Destination, resource: CopyErrorResource::Destination,
sample_count: dst_image.samples(), sample_count: dst_image.samples(),
allowed_sample_counts: SampleCounts { allowed_sample_counts: SampleCounts::SAMPLE_1,
sample1: true,
..SampleCounts::empty()
},
}); });
} }
@ -230,10 +238,7 @@ where
return Err(CopyError::SampleCountInvalid { return Err(CopyError::SampleCountInvalid {
resource: CopyErrorResource::Destination, resource: CopyErrorResource::Destination,
sample_count: dst_image.samples(), sample_count: dst_image.samples(),
allowed_sample_counts: SampleCounts { allowed_sample_counts: SampleCounts::SAMPLE_1,
sample1: true,
..SampleCounts::empty()
},
}); });
} }
@ -260,7 +265,7 @@ where
} }
// VUID-VkBlitImageInfo2-srcImage-00232 // VUID-VkBlitImageInfo2-srcImage-00232
if !src_image_aspects.color && filter != Filter::Nearest { if !src_image_aspects.intersects(ImageAspects::COLOR) && filter != Filter::Nearest {
return Err(CopyError::FilterNotSupportedByFormat); return Err(CopyError::FilterNotSupportedByFormat);
} }
@ -268,13 +273,19 @@ where
Filter::Nearest => (), Filter::Nearest => (),
Filter::Linear => { Filter::Linear => {
// VUID-VkBlitImageInfo2-filter-02001 // VUID-VkBlitImageInfo2-filter-02001
if !src_image.format_features().sampled_image_filter_linear { if !src_image
.format_features()
.intersects(FormatFeatures::SAMPLED_IMAGE_FILTER_LINEAR)
{
return Err(CopyError::FilterNotSupportedByFormat); return Err(CopyError::FilterNotSupportedByFormat);
} }
} }
Filter::Cubic => { Filter::Cubic => {
// VUID-VkBlitImageInfo2-filter-02002 // VUID-VkBlitImageInfo2-filter-02002
if !src_image.format_features().sampled_image_filter_cubic { if !src_image
.format_features()
.intersects(FormatFeatures::SAMPLED_IMAGE_FILTER_CUBIC)
{
return Err(CopyError::FilterNotSupportedByFormat); return Err(CopyError::FilterNotSupportedByFormat);
} }
@ -300,7 +311,7 @@ where
let check_subresource = |resource: CopyErrorResource, let check_subresource = |resource: CopyErrorResource,
image: &dyn ImageAccess, image: &dyn ImageAccess,
image_aspects: &ImageAspects, image_aspects: ImageAspects,
subresource: &ImageSubresourceLayers| subresource: &ImageSubresourceLayers|
-> Result<_, CopyError> { -> Result<_, CopyError> {
// VUID-VkBlitImageInfo2-srcSubresource-01705 // VUID-VkBlitImageInfo2-srcSubresource-01705
@ -337,12 +348,12 @@ where
// VUID-VkBlitImageInfo2-aspectMask-00241 // VUID-VkBlitImageInfo2-aspectMask-00241
// VUID-VkBlitImageInfo2-aspectMask-00242 // VUID-VkBlitImageInfo2-aspectMask-00242
if !image_aspects.contains(&subresource.aspects) { if !image_aspects.contains(subresource.aspects) {
return Err(CopyError::AspectsNotAllowed { return Err(CopyError::AspectsNotAllowed {
resource, resource,
region_index, region_index,
aspects: subresource.aspects, aspects: subresource.aspects,
allowed_aspects: *image_aspects, allowed_aspects: image_aspects,
}); });
} }
@ -356,13 +367,13 @@ where
let src_subresource_extent = check_subresource( let src_subresource_extent = check_subresource(
CopyErrorResource::Source, CopyErrorResource::Source,
src_image, src_image,
&src_image_aspects, src_image_aspects,
src_subresource, src_subresource,
)?; )?;
let dst_subresource_extent = check_subresource( let dst_subresource_extent = check_subresource(
CopyErrorResource::Destination, CopyErrorResource::Destination,
dst_image, dst_image,
&dst_image_aspects, dst_image_aspects,
dst_subresource, dst_subresource,
)?; )?;
@ -591,8 +602,9 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdClearColorImage-commandBuffer-cmdpool // VUID-vkCmdClearColorImage-commandBuffer-cmdpool
if !(queue_family_properties.queue_flags.graphics if !queue_family_properties
|| queue_family_properties.queue_flags.compute) .queue_flags
.intersects(QueueFlags::GRAPHICS | QueueFlags::COMPUTE)
{ {
return Err(CopyError::NotSupportedByQueueFamily); return Err(CopyError::NotSupportedByQueueFamily);
} }
@ -612,7 +624,7 @@ where
assert_eq!(device, image.device()); assert_eq!(device, image.device());
// VUID-vkCmdClearColorImage-image-00002 // VUID-vkCmdClearColorImage-image-00002
if !image.usage().transfer_dst { if !image.usage().intersects(ImageUsage::TRANSFER_DST) {
return Err(CopyError::MissingUsage { return Err(CopyError::MissingUsage {
resource: CopyErrorResource::Destination, resource: CopyErrorResource::Destination,
usage: "transfer_dst", usage: "transfer_dst",
@ -621,7 +633,10 @@ where
if device.api_version() >= Version::V1_1 || device.enabled_extensions().khr_maintenance1 { if device.api_version() >= Version::V1_1 || device.enabled_extensions().khr_maintenance1 {
// VUID-vkCmdClearColorImage-image-01993 // VUID-vkCmdClearColorImage-image-01993
if !image.format_features().transfer_dst { if !image
.format_features()
.intersects(FormatFeatures::TRANSFER_DST)
{
return Err(CopyError::MissingFormatFeature { return Err(CopyError::MissingFormatFeature {
resource: CopyErrorResource::Destination, resource: CopyErrorResource::Destination,
format_feature: "transfer_dst", format_feature: "transfer_dst",
@ -632,7 +647,7 @@ where
let image_aspects = image.format().aspects(); let image_aspects = image.format().aspects();
// VUID-vkCmdClearColorImage-image-00007 // VUID-vkCmdClearColorImage-image-00007
if image_aspects.depth || image_aspects.stencil { if image_aspects.intersects(ImageAspects::DEPTH | ImageAspects::STENCIL) {
return Err(CopyError::FormatNotSupported { return Err(CopyError::FormatNotSupported {
resource: CopyErrorResource::Destination, resource: CopyErrorResource::Destination,
format: image.format(), format: image.format(),
@ -674,7 +689,7 @@ where
assert!(!subresource_range.aspects.is_empty()); assert!(!subresource_range.aspects.is_empty());
// VUID-vkCmdClearColorImage-aspectMask-02498 // VUID-vkCmdClearColorImage-aspectMask-02498
if !image_aspects.contains(&subresource_range.aspects) { if !image_aspects.contains(subresource_range.aspects) {
return Err(CopyError::AspectsNotAllowed { return Err(CopyError::AspectsNotAllowed {
resource: CopyErrorResource::Destination, resource: CopyErrorResource::Destination,
region_index, region_index,
@ -743,7 +758,10 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdClearDepthStencilImage-commandBuffer-cmdpool // VUID-vkCmdClearDepthStencilImage-commandBuffer-cmdpool
if !queue_family_properties.queue_flags.graphics { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS)
{
return Err(CopyError::NotSupportedByQueueFamily); return Err(CopyError::NotSupportedByQueueFamily);
} }
@ -763,7 +781,10 @@ where
if device.api_version() >= Version::V1_1 || device.enabled_extensions().khr_maintenance1 { if device.api_version() >= Version::V1_1 || device.enabled_extensions().khr_maintenance1 {
// VUID-vkCmdClearDepthStencilImage-image-01994 // VUID-vkCmdClearDepthStencilImage-image-01994
if !image.format_features().transfer_dst { if !image
.format_features()
.intersects(FormatFeatures::TRANSFER_DST)
{
return Err(CopyError::MissingFormatFeature { return Err(CopyError::MissingFormatFeature {
resource: CopyErrorResource::Destination, resource: CopyErrorResource::Destination,
format_feature: "transfer_dst", format_feature: "transfer_dst",
@ -774,7 +795,7 @@ where
let image_aspects = image.format().aspects(); let image_aspects = image.format().aspects();
// VUID-vkCmdClearDepthStencilImage-image-00014 // VUID-vkCmdClearDepthStencilImage-image-00014
if !(image_aspects.depth || image_aspects.stencil) { if !image_aspects.intersects(ImageAspects::DEPTH | ImageAspects::STENCIL) {
return Err(CopyError::FormatNotSupported { return Err(CopyError::FormatNotSupported {
resource: CopyErrorResource::Destination, resource: CopyErrorResource::Destination,
format: image.format(), format: image.format(),
@ -797,8 +818,8 @@ where
&& !(0.0..=1.0).contains(&clear_value.depth) && !(0.0..=1.0).contains(&clear_value.depth)
{ {
return Err(CopyError::RequirementNotMet { return Err(CopyError::RequirementNotMet {
required_for: required_for: "`clear_info.clear_value.depth` is not between `0.0` and `1.0` \
"`clear_info.clear_value.depth` is not between `0.0` and `1.0` inclusive", inclusive",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
device_extensions: &["ext_depth_range_unrestricted"], device_extensions: &["ext_depth_range_unrestricted"],
..Default::default() ..Default::default()
@ -818,7 +839,7 @@ where
// VUID-vkCmdClearDepthStencilImage-aspectMask-02824 // VUID-vkCmdClearDepthStencilImage-aspectMask-02824
// VUID-vkCmdClearDepthStencilImage-image-02825 // VUID-vkCmdClearDepthStencilImage-image-02825
// VUID-vkCmdClearDepthStencilImage-image-02826 // VUID-vkCmdClearDepthStencilImage-image-02826
if !image_aspects.contains(&subresource_range.aspects) { if !image_aspects.contains(subresource_range.aspects) {
return Err(CopyError::AspectsNotAllowed { return Err(CopyError::AspectsNotAllowed {
resource: CopyErrorResource::Destination, resource: CopyErrorResource::Destination,
region_index, region_index,
@ -860,7 +881,9 @@ where
// VUID-vkCmdClearDepthStencilImage-pRanges-02658 // VUID-vkCmdClearDepthStencilImage-pRanges-02658
// VUID-vkCmdClearDepthStencilImage-pRanges-02659 // VUID-vkCmdClearDepthStencilImage-pRanges-02659
if image_aspects_used.stencil && !image.stencil_usage().transfer_dst { if image_aspects_used.intersects(ImageAspects::STENCIL)
&& !image.stencil_usage().intersects(ImageUsage::TRANSFER_DST)
{
return Err(CopyError::MissingUsage { return Err(CopyError::MissingUsage {
resource: CopyErrorResource::Destination, resource: CopyErrorResource::Destination,
usage: "transfer_dst", usage: "transfer_dst",
@ -868,12 +891,8 @@ where
} }
// VUID-vkCmdClearDepthStencilImage-pRanges-02660 // VUID-vkCmdClearDepthStencilImage-pRanges-02660
if !(ImageAspects { if !(image_aspects_used - ImageAspects::STENCIL).is_empty()
stencil: false, && !image.usage().intersects(ImageUsage::TRANSFER_DST)
..image_aspects_used
})
.is_empty()
&& !image.usage().transfer_dst
{ {
return Err(CopyError::MissingUsage { return Err(CopyError::MissingUsage {
resource: CopyErrorResource::Destination, resource: CopyErrorResource::Destination,
@ -917,7 +936,10 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdResolveImage2-commandBuffer-cmdpool // VUID-vkCmdResolveImage2-commandBuffer-cmdpool
if !queue_family_properties.queue_flags.graphics { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS)
{
return Err(CopyError::NotSupportedByQueueFamily); return Err(CopyError::NotSupportedByQueueFamily);
} }
@ -948,15 +970,12 @@ where
return Err(CopyError::SampleCountInvalid { return Err(CopyError::SampleCountInvalid {
resource: CopyErrorResource::Source, resource: CopyErrorResource::Source,
sample_count: dst_image.samples(), sample_count: dst_image.samples(),
allowed_sample_counts: SampleCounts { allowed_sample_counts: SampleCounts::SAMPLE_2
sample2: true, | SampleCounts::SAMPLE_4
sample4: true, | SampleCounts::SAMPLE_8
sample8: true, | SampleCounts::SAMPLE_16
sample16: true, | SampleCounts::SAMPLE_32
sample32: true, | SampleCounts::SAMPLE_64,
sample64: true,
..SampleCounts::empty()
},
}); });
} }
@ -965,15 +984,15 @@ where
return Err(CopyError::SampleCountInvalid { return Err(CopyError::SampleCountInvalid {
resource: CopyErrorResource::Destination, resource: CopyErrorResource::Destination,
sample_count: dst_image.samples(), sample_count: dst_image.samples(),
allowed_sample_counts: SampleCounts { allowed_sample_counts: SampleCounts::SAMPLE_1,
sample1: true,
..SampleCounts::empty()
},
}); });
} }
// VUID-VkResolveImageInfo2-dstImage-02003 // VUID-VkResolveImageInfo2-dstImage-02003
if !dst_image.format_features().color_attachment { if !dst_image
.format_features()
.intersects(FormatFeatures::COLOR_ATTACHMENT)
{
return Err(CopyError::MissingFormatFeature { return Err(CopyError::MissingFormatFeature {
resource: CopyErrorResource::Destination, resource: CopyErrorResource::Destination,
format_feature: "color_attachment", format_feature: "color_attachment",
@ -1012,7 +1031,10 @@ where
// Should be guaranteed by the requirement that formats match, and that the destination // Should be guaranteed by the requirement that formats match, and that the destination
// image format features support color attachments. // image format features support color attachments.
debug_assert!(src_image.format().aspects().color && dst_image.format().aspects().color); debug_assert!(
src_image.format().aspects().intersects(ImageAspects::COLOR)
&& dst_image.format().aspects().intersects(ImageAspects::COLOR)
);
for (region_index, region) in regions.iter().enumerate() { for (region_index, region) in regions.iter().enumerate() {
let &ImageResolve { let &ImageResolve {
@ -1062,20 +1084,12 @@ where
// VUID-VkImageSubresourceLayers-aspectMask-requiredbitmask // VUID-VkImageSubresourceLayers-aspectMask-requiredbitmask
// VUID-VkImageResolve2-aspectMask-00266 // VUID-VkImageResolve2-aspectMask-00266
if subresource.aspects if subresource.aspects != (ImageAspects::COLOR) {
!= (ImageAspects {
color: true,
..ImageAspects::empty()
})
{
return Err(CopyError::AspectsNotAllowed { return Err(CopyError::AspectsNotAllowed {
resource, resource,
region_index, region_index,
aspects: subresource.aspects, aspects: subresource.aspects,
allowed_aspects: ImageAspects { allowed_aspects: ImageAspects::COLOR,
color: true,
..ImageAspects::empty()
},
}); });
} }
@ -1216,14 +1230,8 @@ impl SyncCommandBufferBuilder {
image: src_image.clone(), image: src_image.clone(),
subresource_range: src_subresource.clone().into(), subresource_range: src_subresource.clone().into(),
memory: PipelineMemoryAccess { memory: PipelineMemoryAccess {
stages: PipelineStages { stages: PipelineStages::ALL_TRANSFER,
all_transfer: true, access: AccessFlags::TRANSFER_READ,
..PipelineStages::empty()
},
access: AccessFlags {
transfer_read: true,
..AccessFlags::empty()
},
exclusive: false, exclusive: false,
}, },
start_layout: src_image_layout, start_layout: src_image_layout,
@ -1236,14 +1244,8 @@ impl SyncCommandBufferBuilder {
image: dst_image.clone(), image: dst_image.clone(),
subresource_range: dst_subresource.clone().into(), subresource_range: dst_subresource.clone().into(),
memory: PipelineMemoryAccess { memory: PipelineMemoryAccess {
stages: PipelineStages { stages: PipelineStages::ALL_TRANSFER,
all_transfer: true, access: AccessFlags::TRANSFER_WRITE,
..PipelineStages::empty()
},
access: AccessFlags {
transfer_write: true,
..AccessFlags::empty()
},
exclusive: true, exclusive: true,
}, },
start_layout: dst_image_layout, start_layout: dst_image_layout,
@ -1308,14 +1310,8 @@ impl SyncCommandBufferBuilder {
image: image.clone(), image: image.clone(),
subresource_range, subresource_range,
memory: PipelineMemoryAccess { memory: PipelineMemoryAccess {
stages: PipelineStages { stages: PipelineStages::ALL_TRANSFER,
all_transfer: true, access: AccessFlags::TRANSFER_WRITE,
..PipelineStages::empty()
},
access: AccessFlags {
transfer_write: true,
..AccessFlags::empty()
},
exclusive: true, exclusive: true,
}, },
start_layout: image_layout, start_layout: image_layout,
@ -1379,14 +1375,8 @@ impl SyncCommandBufferBuilder {
image: image.clone(), image: image.clone(),
subresource_range, subresource_range,
memory: PipelineMemoryAccess { memory: PipelineMemoryAccess {
stages: PipelineStages { stages: PipelineStages::ALL_TRANSFER,
all_transfer: true, access: AccessFlags::TRANSFER_WRITE,
..PipelineStages::empty()
},
access: AccessFlags {
transfer_write: true,
..AccessFlags::empty()
},
exclusive: true, exclusive: true,
}, },
start_layout: image_layout, start_layout: image_layout,
@ -1460,14 +1450,8 @@ impl SyncCommandBufferBuilder {
image: src_image.clone(), image: src_image.clone(),
subresource_range: src_subresource.clone().into(), subresource_range: src_subresource.clone().into(),
memory: PipelineMemoryAccess { memory: PipelineMemoryAccess {
stages: PipelineStages { stages: PipelineStages::ALL_TRANSFER,
all_transfer: true, access: AccessFlags::TRANSFER_READ,
..PipelineStages::empty()
},
access: AccessFlags {
transfer_read: true,
..AccessFlags::empty()
},
exclusive: false, exclusive: false,
}, },
start_layout: src_image_layout, start_layout: src_image_layout,
@ -1480,14 +1464,8 @@ impl SyncCommandBufferBuilder {
image: dst_image.clone(), image: dst_image.clone(),
subresource_range: dst_subresource.clone().into(), subresource_range: dst_subresource.clone().into(),
memory: PipelineMemoryAccess { memory: PipelineMemoryAccess {
stages: PipelineStages { stages: PipelineStages::ALL_TRANSFER,
all_transfer: true, access: AccessFlags::TRANSFER_WRITE,
..PipelineStages::empty()
},
access: AccessFlags {
transfer_write: true,
..AccessFlags::empty()
},
exclusive: true, exclusive: true,
}, },
start_layout: dst_image_layout, start_layout: dst_image_layout,

View File

@ -8,7 +8,7 @@
// according to those terms. // according to those terms.
use crate::{ use crate::{
buffer::{view::BufferViewAbstract, BufferAccess, TypedBufferAccess}, buffer::{view::BufferViewAbstract, BufferAccess, BufferUsage, TypedBufferAccess},
command_buffer::{ command_buffer::{
allocator::CommandBufferAllocator, allocator::CommandBufferAllocator,
auto::{RenderPassState, RenderPassStateType}, auto::{RenderPassState, RenderPassStateType},
@ -18,10 +18,11 @@ use crate::{
DrawIndirectCommand, SubpassContents, DrawIndirectCommand, SubpassContents,
}, },
descriptor_set::{layout::DescriptorType, DescriptorBindingResources}, descriptor_set::{layout::DescriptorType, DescriptorBindingResources},
device::DeviceOwned, device::{DeviceOwned, QueueFlags},
format::Format, format::{Format, FormatFeatures},
image::{ image::{
view::ImageViewType, ImageAccess, ImageSubresourceRange, ImageViewAbstract, SampleCount, view::ImageViewType, ImageAccess, ImageAspects, ImageSubresourceRange, ImageViewAbstract,
SampleCount,
}, },
pipeline::{ pipeline::{
graphics::{ graphics::{
@ -76,7 +77,10 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdDispatch-commandBuffer-cmdpool // VUID-vkCmdDispatch-commandBuffer-cmdpool
if !queue_family_properties.queue_flags.compute { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::COMPUTE)
{
return Err(PipelineExecutionError::NotSupportedByQueueFamily); return Err(PipelineExecutionError::NotSupportedByQueueFamily);
} }
@ -142,7 +146,10 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdDispatchIndirect-commandBuffer-cmdpool // VUID-vkCmdDispatchIndirect-commandBuffer-cmdpool
if !queue_family_properties.queue_flags.compute { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::COMPUTE)
{
return Err(PipelineExecutionError::NotSupportedByQueueFamily); return Err(PipelineExecutionError::NotSupportedByQueueFamily);
} }
@ -549,7 +556,7 @@ where
assert_eq!(self.device(), buffer.device()); assert_eq!(self.device(), buffer.device());
// VUID-vkCmdDispatchIndirect-buffer-02709 // VUID-vkCmdDispatchIndirect-buffer-02709
if !buffer.inner().buffer.usage().indirect_buffer { if !buffer.usage().intersects(BufferUsage::INDIRECT_BUFFER) {
return Err(PipelineExecutionError::IndirectBufferMissingUsage); return Err(PipelineExecutionError::IndirectBufferMissingUsage);
} }
@ -650,7 +657,9 @@ where
// VUID-vkCmdDispatch-OpTypeImage-06423 // VUID-vkCmdDispatch-OpTypeImage-06423
if reqs.image_format.is_none() if reqs.image_format.is_none()
&& reqs.storage_write.contains(&index) && reqs.storage_write.contains(&index)
&& !buffer_view.format_features().storage_write_without_format && !buffer_view
.format_features()
.intersects(FormatFeatures::STORAGE_WRITE_WITHOUT_FORMAT)
{ {
return Err( return Err(
DescriptorResourceInvalidError::StorageWriteWithoutFormatNotSupported, DescriptorResourceInvalidError::StorageWriteWithoutFormatNotSupported,
@ -660,7 +669,9 @@ where
// VUID-vkCmdDispatch-OpTypeImage-06424 // VUID-vkCmdDispatch-OpTypeImage-06424
if reqs.image_format.is_none() if reqs.image_format.is_none()
&& reqs.storage_read.contains(&index) && reqs.storage_read.contains(&index)
&& !buffer_view.format_features().storage_read_without_format && !buffer_view
.format_features()
.intersects(FormatFeatures::STORAGE_READ_WITHOUT_FORMAT)
{ {
return Err( return Err(
DescriptorResourceInvalidError::StorageReadWithoutFormatNotSupported, DescriptorResourceInvalidError::StorageReadWithoutFormatNotSupported,
@ -674,7 +685,9 @@ where
let check_image_view_common = |index: u32, image_view: &Arc<dyn ImageViewAbstract>| { let check_image_view_common = |index: u32, image_view: &Arc<dyn ImageViewAbstract>| {
// VUID-vkCmdDispatch-None-02691 // VUID-vkCmdDispatch-None-02691
if reqs.storage_image_atomic.contains(&index) if reqs.storage_image_atomic.contains(&index)
&& !image_view.format_features().storage_image_atomic && !image_view
.format_features()
.intersects(FormatFeatures::STORAGE_IMAGE_ATOMIC)
{ {
return Err(DescriptorResourceInvalidError::StorageImageAtomicNotSupported); return Err(DescriptorResourceInvalidError::StorageImageAtomicNotSupported);
} }
@ -683,7 +696,9 @@ where
// VUID-vkCmdDispatch-OpTypeImage-06423 // VUID-vkCmdDispatch-OpTypeImage-06423
if reqs.image_format.is_none() if reqs.image_format.is_none()
&& reqs.storage_write.contains(&index) && reqs.storage_write.contains(&index)
&& !image_view.format_features().storage_write_without_format && !image_view
.format_features()
.intersects(FormatFeatures::STORAGE_WRITE_WITHOUT_FORMAT)
{ {
return Err( return Err(
DescriptorResourceInvalidError::StorageWriteWithoutFormatNotSupported, DescriptorResourceInvalidError::StorageWriteWithoutFormatNotSupported,
@ -693,7 +708,9 @@ where
// VUID-vkCmdDispatch-OpTypeImage-06424 // VUID-vkCmdDispatch-OpTypeImage-06424
if reqs.image_format.is_none() if reqs.image_format.is_none()
&& reqs.storage_read.contains(&index) && reqs.storage_read.contains(&index)
&& !image_view.format_features().storage_read_without_format && !image_view
.format_features()
.intersects(FormatFeatures::STORAGE_READ_WITHOUT_FORMAT)
{ {
return Err( return Err(
DescriptorResourceInvalidError::StorageReadWithoutFormatNotSupported, DescriptorResourceInvalidError::StorageReadWithoutFormatNotSupported,
@ -748,11 +765,16 @@ where
if let Some(scalar_type) = reqs.image_scalar_type { if let Some(scalar_type) = reqs.image_scalar_type {
let aspects = image_view.subresource_range().aspects; let aspects = image_view.subresource_range().aspects;
let view_scalar_type = ShaderScalarType::from( let view_scalar_type = ShaderScalarType::from(
if aspects.color || aspects.plane0 || aspects.plane1 || aspects.plane2 { if aspects.intersects(
ImageAspects::COLOR
| ImageAspects::PLANE_0
| ImageAspects::PLANE_1
| ImageAspects::PLANE_2,
) {
image_view.format().unwrap().type_color().unwrap() image_view.format().unwrap().type_color().unwrap()
} else if aspects.depth { } else if aspects.intersects(ImageAspects::DEPTH) {
image_view.format().unwrap().type_depth().unwrap() image_view.format().unwrap().type_depth().unwrap()
} else if aspects.stencil { } else if aspects.intersects(ImageAspects::STENCIL) {
image_view.format().unwrap().type_stencil().unwrap() image_view.format().unwrap().type_stencil().unwrap()
} else { } else {
// Per `ImageViewBuilder::aspects` and // Per `ImageViewBuilder::aspects` and
@ -1125,7 +1147,10 @@ where
// VUID? // VUID?
if !device.enabled_features().primitive_topology_list_restart { if !device.enabled_features().primitive_topology_list_restart {
return Err(PipelineExecutionError::RequirementNotMet { return Err(PipelineExecutionError::RequirementNotMet {
required_for: "The bound pipeline sets `DynamicState::PrimitiveRestartEnable` and the current primitive topology is `PrimitiveTopology::*List`", required_for: "The bound pipeline sets \
`DynamicState::PrimitiveRestartEnable` and the \
current primitive topology is \
`PrimitiveTopology::*List`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["primitive_topology_list_restart"], features: &["primitive_topology_list_restart"],
..Default::default() ..Default::default()
@ -1140,7 +1165,10 @@ where
.primitive_topology_patch_list_restart .primitive_topology_patch_list_restart
{ {
return Err(PipelineExecutionError::RequirementNotMet { return Err(PipelineExecutionError::RequirementNotMet {
required_for: "The bound pipeline sets `DynamicState::PrimitiveRestartEnable` and the current primitive topology is `PrimitiveTopology::PatchList`", required_for: "The bound pipeline sets \
`DynamicState::PrimitiveRestartEnable` and the \
current primitive topology is \
`PrimitiveTopology::PatchList`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["primitive_topology_patch_list_restart"], features: &["primitive_topology_patch_list_restart"],
..Default::default() ..Default::default()
@ -1934,20 +1962,10 @@ impl SyncCommandBufferBuilder {
| DescriptorType::UniformTexelBuffer | DescriptorType::UniformTexelBuffer
| DescriptorType::StorageTexelBuffer | DescriptorType::StorageTexelBuffer
| DescriptorType::StorageBuffer | DescriptorType::StorageBuffer
| DescriptorType::StorageBufferDynamic => AccessFlags { | DescriptorType::StorageBufferDynamic => AccessFlags::SHADER_READ,
shader_read: true, DescriptorType::InputAttachment => AccessFlags::INPUT_ATTACHMENT_READ,
shader_write: false,
..AccessFlags::empty()
},
DescriptorType::InputAttachment => AccessFlags {
input_attachment_read: true,
..AccessFlags::empty()
},
DescriptorType::UniformBuffer | DescriptorType::UniformBufferDynamic => { DescriptorType::UniformBuffer | DescriptorType::UniformBufferDynamic => {
AccessFlags { AccessFlags::UNIFORM_READ
uniform_read: true,
..AccessFlags::empty()
}
} }
}, },
exclusive: false, exclusive: false,
@ -1956,8 +1974,12 @@ impl SyncCommandBufferBuilder {
let access = (0..).map(|index| { let access = (0..).map(|index| {
let mut access = access; let mut access = access;
let mutable = reqs.storage_write.contains(&index); let mutable = reqs.storage_write.contains(&index);
access.access.shader_write = mutable;
access.exclusive = mutable; access.exclusive = mutable;
if mutable {
access.access |= AccessFlags::SHADER_WRITE;
}
access access
}); });
@ -2080,14 +2102,8 @@ impl SyncCommandBufferBuilder {
buffer: vertex_buffer.clone(), buffer: vertex_buffer.clone(),
range: 0..vertex_buffer.size(), // TODO: range: 0..vertex_buffer.size(), // TODO:
memory: PipelineMemoryAccess { memory: PipelineMemoryAccess {
stages: PipelineStages { stages: PipelineStages::VERTEX_INPUT,
vertex_input: true, access: AccessFlags::VERTEX_ATTRIBUTE_READ,
..PipelineStages::empty()
},
access: AccessFlags {
vertex_attribute_read: true,
..AccessFlags::empty()
},
exclusive: false, exclusive: false,
}, },
}, },
@ -2103,14 +2119,8 @@ impl SyncCommandBufferBuilder {
buffer: index_buffer.clone(), buffer: index_buffer.clone(),
range: 0..index_buffer.size(), // TODO: range: 0..index_buffer.size(), // TODO:
memory: PipelineMemoryAccess { memory: PipelineMemoryAccess {
stages: PipelineStages { stages: PipelineStages::VERTEX_INPUT,
vertex_input: true, access: AccessFlags::INDEX_READ,
..PipelineStages::empty()
},
access: AccessFlags {
index_read: true,
..AccessFlags::empty()
},
exclusive: false, exclusive: false,
}, },
}, },
@ -2128,14 +2138,8 @@ impl SyncCommandBufferBuilder {
buffer: indirect_buffer.clone(), buffer: indirect_buffer.clone(),
range: 0..indirect_buffer.size(), // TODO: range: 0..indirect_buffer.size(), // TODO:
memory: PipelineMemoryAccess { memory: PipelineMemoryAccess {
stages: PipelineStages { stages: PipelineStages::DRAW_INDIRECT, // TODO: is draw_indirect correct for dispatch too?
draw_indirect: true, access: AccessFlags::INDIRECT_COMMAND_READ,
..PipelineStages::empty()
}, // TODO: is draw_indirect correct for dispatch too?
access: AccessFlags {
indirect_command_read: true,
..AccessFlags::empty()
},
exclusive: false, exclusive: false,
}, },
}, },
@ -2174,7 +2178,10 @@ impl UnsafeCommandBufferBuilder {
let inner = buffer.inner(); let inner = buffer.inner();
debug_assert!(inner.offset < inner.buffer.size()); debug_assert!(inner.offset < inner.buffer.size());
debug_assert!(inner.buffer.usage().indirect_buffer); debug_assert!(inner
.buffer
.usage()
.intersects(BufferUsage::INDIRECT_BUFFER));
debug_assert_eq!(inner.offset % 4, 0); debug_assert_eq!(inner.offset % 4, 0);
(fns.v1_0.cmd_dispatch_indirect)(self.handle, inner.buffer.handle(), inner.offset); (fns.v1_0.cmd_dispatch_indirect)(self.handle, inner.buffer.handle(), inner.offset);
@ -2238,7 +2245,10 @@ impl UnsafeCommandBufferBuilder {
let inner = buffer.inner(); let inner = buffer.inner();
debug_assert!(inner.offset < inner.buffer.size()); debug_assert!(inner.offset < inner.buffer.size());
debug_assert!(inner.buffer.usage().indirect_buffer); debug_assert!(inner
.buffer
.usage()
.intersects(BufferUsage::INDIRECT_BUFFER));
(fns.v1_0.cmd_draw_indirect)( (fns.v1_0.cmd_draw_indirect)(
self.handle, self.handle,
@ -2261,7 +2271,10 @@ impl UnsafeCommandBufferBuilder {
let inner = buffer.inner(); let inner = buffer.inner();
debug_assert!(inner.offset < inner.buffer.size()); debug_assert!(inner.offset < inner.buffer.size());
debug_assert!(inner.buffer.usage().indirect_buffer); debug_assert!(inner
.buffer
.usage()
.intersects(BufferUsage::INDIRECT_BUFFER));
(fns.v1_0.cmd_draw_indexed_indirect)( (fns.v1_0.cmd_draw_indexed_indirect)(
self.handle, self.handle,

View File

@ -8,7 +8,7 @@
// according to those terms. // according to those terms.
use crate::{ use crate::{
buffer::TypedBufferAccess, buffer::{BufferUsage, TypedBufferAccess},
command_buffer::{ command_buffer::{
allocator::CommandBufferAllocator, allocator::CommandBufferAllocator,
auto::QueryState, auto::QueryState,
@ -16,7 +16,7 @@ use crate::{
sys::UnsafeCommandBufferBuilder, sys::UnsafeCommandBufferBuilder,
AutoCommandBufferBuilder, AutoCommandBufferBuilder,
}, },
device::DeviceOwned, device::{DeviceOwned, QueueFlags},
query::{ query::{
QueriesRange, Query, QueryControlFlags, QueryPool, QueryResultElement, QueryResultFlags, QueriesRange, Query, QueryControlFlags, QueryPool, QueryResultElement, QueryResultFlags,
QueryType, QueryType,
@ -80,8 +80,9 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdBeginQuery-commandBuffer-cmdpool // VUID-vkCmdBeginQuery-commandBuffer-cmdpool
if !(queue_family_properties.queue_flags.graphics if !queue_family_properties
|| queue_family_properties.queue_flags.compute) .queue_flags
.intersects(QueueFlags::GRAPHICS | QueueFlags::COMPUTE)
{ {
return Err(QueryError::NotSupportedByQueueFamily); return Err(QueryError::NotSupportedByQueueFamily);
} }
@ -101,14 +102,19 @@ where
QueryType::Occlusion => { QueryType::Occlusion => {
// VUID-vkCmdBeginQuery-commandBuffer-cmdpool // VUID-vkCmdBeginQuery-commandBuffer-cmdpool
// // VUID-vkCmdBeginQuery-queryType-00803 // // VUID-vkCmdBeginQuery-queryType-00803
if !queue_family_properties.queue_flags.graphics { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS)
{
return Err(QueryError::NotSupportedByQueueFamily); return Err(QueryError::NotSupportedByQueueFamily);
} }
// VUID-vkCmdBeginQuery-queryType-00800 // VUID-vkCmdBeginQuery-queryType-00800
if flags.precise && !device.enabled_features().occlusion_query_precise { if flags.intersects(QueryControlFlags::PRECISE)
&& !device.enabled_features().occlusion_query_precise
{
return Err(QueryError::RequirementNotMet { return Err(QueryError::RequirementNotMet {
required_for: "`flags.precise` is set", required_for: "`flags` contains `QueryControlFlags::PRECISE`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["occlusion_query_precise"], features: &["occlusion_query_precise"],
..Default::default() ..Default::default()
@ -120,15 +126,20 @@ where
// VUID-vkCmdBeginQuery-commandBuffer-cmdpool // VUID-vkCmdBeginQuery-commandBuffer-cmdpool
// VUID-vkCmdBeginQuery-queryType-00804 // VUID-vkCmdBeginQuery-queryType-00804
// VUID-vkCmdBeginQuery-queryType-00805 // VUID-vkCmdBeginQuery-queryType-00805
if statistic_flags.is_compute() && !queue_family_properties.queue_flags.compute if statistic_flags.is_compute()
&& !queue_family_properties
.queue_flags
.intersects(QueueFlags::COMPUTE)
|| statistic_flags.is_graphics() || statistic_flags.is_graphics()
&& !queue_family_properties.queue_flags.graphics && !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS)
{ {
return Err(QueryError::NotSupportedByQueueFamily); return Err(QueryError::NotSupportedByQueueFamily);
} }
// VUID-vkCmdBeginQuery-queryType-00800 // VUID-vkCmdBeginQuery-queryType-00800
if flags.precise { if flags.intersects(QueryControlFlags::PRECISE) {
return Err(QueryError::InvalidFlags); return Err(QueryError::InvalidFlags);
} }
} }
@ -179,8 +190,9 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdEndQuery-commandBuffer-cmdpool // VUID-vkCmdEndQuery-commandBuffer-cmdpool
if !(queue_family_properties.queue_flags.graphics if !queue_family_properties
|| queue_family_properties.queue_flags.compute) .queue_flags
.intersects(QueueFlags::GRAPHICS | QueueFlags::COMPUTE)
{ {
return Err(QueryError::NotSupportedByQueueFamily); return Err(QueryError::NotSupportedByQueueFamily);
} }
@ -243,7 +255,7 @@ where
if !device.enabled_features().synchronization2 && PipelineStages::from(stage).is_2() { if !device.enabled_features().synchronization2 && PipelineStages::from(stage).is_2() {
return Err(QueryError::RequirementNotMet { return Err(QueryError::RequirementNotMet {
required_for: "`stage` has bits set from `VkPipelineStageFlagBits2`", required_for: "`stage` has flags set from `VkPipelineStageFlagBits2`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["synchronization2"], features: &["synchronization2"],
..Default::default() ..Default::default()
@ -257,12 +269,13 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdWriteTimestamp2-commandBuffer-cmdpool // VUID-vkCmdWriteTimestamp2-commandBuffer-cmdpool
if !(queue_family_properties.queue_flags.transfer if !queue_family_properties.queue_flags.intersects(
|| queue_family_properties.queue_flags.graphics QueueFlags::TRANSFER
|| queue_family_properties.queue_flags.compute | QueueFlags::GRAPHICS
|| queue_family_properties.queue_flags.video_decode | QueueFlags::COMPUTE
|| queue_family_properties.queue_flags.video_encode) | QueueFlags::VIDEO_DECODE
{ | QueueFlags::VIDEO_ENCODE,
) {
return Err(QueryError::NotSupportedByQueueFamily); return Err(QueryError::NotSupportedByQueueFamily);
} }
@ -294,7 +307,8 @@ where
// VUID-vkCmdWriteTimestamp2-stage-03930 // VUID-vkCmdWriteTimestamp2-stage-03930
if !device.enabled_features().tessellation_shader { if !device.enabled_features().tessellation_shader {
return Err(QueryError::RequirementNotMet { return Err(QueryError::RequirementNotMet {
required_for: "`stage` is `PipelineStage::TessellationControlShader` or `PipelineStage::TessellationEvaluationShader`", required_for: "`stage` is `PipelineStage::TessellationControlShader` or \
`PipelineStage::TessellationEvaluationShader`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["tessellation_shader"], features: &["tessellation_shader"],
..Default::default() ..Default::default()
@ -433,12 +447,15 @@ where
/// Copies the results of a range of queries to a buffer on the GPU. /// Copies the results of a range of queries to a buffer on the GPU.
/// ///
/// [`query_pool.ty().result_len()`](crate::query::QueryType::result_len) elements /// [`query_pool.ty().result_len()`] elements will be written for each query in the range, plus
/// will be written for each query in the range, plus 1 extra element per query if /// 1 extra element per query if [`QueryResultFlags::WITH_AVAILABILITY`] is enabled.
/// [`QueryResultFlags::with_availability`] is enabled.
/// The provided buffer must be large enough to hold the data. /// The provided buffer must be large enough to hold the data.
/// ///
/// See also [`get_results`](crate::query::QueriesRange::get_results). /// See also [`get_results`].
///
/// [`query_pool.ty().result_len()`]: crate::query::QueryType::result_len
/// [`QueryResultFlags::WITH_AVAILABILITY`]: crate::query::QueryResultFlags::WITH_AVAILABILITY
/// [`get_results`]: crate::query::QueriesRange::get_results
pub fn copy_query_pool_results<D, T>( pub fn copy_query_pool_results<D, T>(
&mut self, &mut self,
query_pool: Arc<QueryPool>, query_pool: Arc<QueryPool>,
@ -458,8 +475,8 @@ where
)?; )?;
unsafe { unsafe {
let per_query_len = let per_query_len = query_pool.query_type().result_len()
query_pool.query_type().result_len() + flags.with_availability as DeviceSize; + flags.intersects(QueryResultFlags::WITH_AVAILABILITY) as DeviceSize;
let stride = per_query_len * std::mem::size_of::<T>() as DeviceSize; let stride = per_query_len * std::mem::size_of::<T>() as DeviceSize;
self.inner self.inner
.copy_query_pool_results(query_pool, queries, destination, stride, flags)?; .copy_query_pool_results(query_pool, queries, destination, stride, flags)?;
@ -482,8 +499,9 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdCopyQueryPoolResults-commandBuffer-cmdpool // VUID-vkCmdCopyQueryPoolResults-commandBuffer-cmdpool
if !(queue_family_properties.queue_flags.graphics if !queue_family_properties
|| queue_family_properties.queue_flags.compute) .queue_flags
.intersects(QueueFlags::GRAPHICS | QueueFlags::COMPUTE)
{ {
return Err(QueryError::NotSupportedByQueueFamily); return Err(QueryError::NotSupportedByQueueFamily);
} }
@ -513,8 +531,8 @@ where
.ok_or(QueryError::OutOfRange)?; .ok_or(QueryError::OutOfRange)?;
let count = queries.end - queries.start; let count = queries.end - queries.start;
let per_query_len = let per_query_len = query_pool.query_type().result_len()
query_pool.query_type().result_len() + flags.with_availability as DeviceSize; + flags.intersects(QueryResultFlags::WITH_AVAILABILITY) as DeviceSize;
let required_len = per_query_len * count as DeviceSize; let required_len = per_query_len * count as DeviceSize;
// VUID-vkCmdCopyQueryPoolResults-dstBuffer-00824 // VUID-vkCmdCopyQueryPoolResults-dstBuffer-00824
@ -526,12 +544,18 @@ where
} }
// VUID-vkCmdCopyQueryPoolResults-dstBuffer-00825 // VUID-vkCmdCopyQueryPoolResults-dstBuffer-00825
if !buffer_inner.buffer.usage().transfer_dst { if !buffer_inner
.buffer
.usage()
.intersects(BufferUsage::TRANSFER_DST)
{
return Err(QueryError::DestinationMissingUsage); return Err(QueryError::DestinationMissingUsage);
} }
// VUID-vkCmdCopyQueryPoolResults-queryType-00827 // VUID-vkCmdCopyQueryPoolResults-queryType-00827
if matches!(query_pool.query_type(), QueryType::Timestamp) && flags.partial { if matches!(query_pool.query_type(), QueryType::Timestamp)
&& flags.intersects(QueryResultFlags::PARTIAL)
{
return Err(QueryError::InvalidFlags); return Err(QueryError::InvalidFlags);
} }
@ -571,8 +595,9 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdResetQueryPool-commandBuffer-cmdpool // VUID-vkCmdResetQueryPool-commandBuffer-cmdpool
if !(queue_family_properties.queue_flags.graphics if !queue_family_properties
|| queue_family_properties.queue_flags.compute) .queue_flags
.intersects(QueueFlags::GRAPHICS | QueueFlags::COMPUTE)
{ {
return Err(QueryError::NotSupportedByQueueFamily); return Err(QueryError::NotSupportedByQueueFamily);
} }
@ -734,14 +759,8 @@ impl SyncCommandBufferBuilder {
buffer: destination.clone(), buffer: destination.clone(),
range: 0..destination.size(), // TODO: range: 0..destination.size(), // TODO:
memory: PipelineMemoryAccess { memory: PipelineMemoryAccess {
stages: PipelineStages { stages: PipelineStages::ALL_TRANSFER,
all_transfer: true, access: AccessFlags::TRANSFER_WRITE,
..PipelineStages::empty()
},
access: AccessFlags {
transfer_write: true,
..AccessFlags::empty()
},
exclusive: true, exclusive: true,
}, },
}, },
@ -796,12 +815,12 @@ impl UnsafeCommandBufferBuilder {
#[inline] #[inline]
pub unsafe fn begin_query(&mut self, query: Query<'_>, flags: QueryControlFlags) { pub unsafe fn begin_query(&mut self, query: Query<'_>, flags: QueryControlFlags) {
let fns = self.device.fns(); let fns = self.device.fns();
let flags = if flags.precise { (fns.v1_0.cmd_begin_query)(
ash::vk::QueryControlFlags::PRECISE self.handle,
} else { query.pool().handle(),
ash::vk::QueryControlFlags::empty() query.index(),
}; flags.into(),
(fns.v1_0.cmd_begin_query)(self.handle, query.pool().handle(), query.index(), flags); );
} }
/// Calls `vkCmdEndQuery` on the builder. /// Calls `vkCmdEndQuery` on the builder.
@ -857,7 +876,10 @@ impl UnsafeCommandBufferBuilder {
let destination = destination.inner(); let destination = destination.inner();
let range = queries.range(); let range = queries.range();
debug_assert!(destination.offset < destination.buffer.size()); debug_assert!(destination.offset < destination.buffer.size());
debug_assert!(destination.buffer.usage().transfer_dst); debug_assert!(destination
.buffer
.usage()
.intersects(BufferUsage::TRANSFER_DST));
debug_assert!(destination.offset % size_of::<T>() as DeviceSize == 0); debug_assert!(destination.offset % size_of::<T>() as DeviceSize == 0);
debug_assert!(stride % size_of::<T>() as DeviceSize == 0); debug_assert!(stride % size_of::<T>() as DeviceSize == 0);

View File

@ -18,9 +18,9 @@ use crate::{
sys::UnsafeCommandBufferBuilder, sys::UnsafeCommandBufferBuilder,
AutoCommandBufferBuilder, SubpassContents, AutoCommandBufferBuilder, SubpassContents,
}, },
device::DeviceOwned, device::{DeviceOwned, QueueFlags},
format::{ClearColorValue, ClearValue, Format, NumericType}, format::{ClearColorValue, ClearValue, Format, NumericType},
image::{ImageLayout, ImageViewAbstract, SampleCount}, image::{ImageAspects, ImageLayout, ImageUsage, ImageViewAbstract, SampleCount},
render_pass::{ render_pass::{
AttachmentDescription, Framebuffer, LoadOp, RenderPass, ResolveMode, StoreOp, AttachmentDescription, Framebuffer, LoadOp, RenderPass, ResolveMode, StoreOp,
SubpassDescription, SubpassDescription,
@ -103,7 +103,10 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdBeginRenderPass2-commandBuffer-cmdpool // VUID-vkCmdBeginRenderPass2-commandBuffer-cmdpool
if !queue_family_properties.queue_flags.graphics { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS)
{
return Err(RenderPassError::NotSupportedByQueueFamily); return Err(RenderPassError::NotSupportedByQueueFamily);
} }
@ -155,7 +158,7 @@ where
match layout { match layout {
ImageLayout::ColorAttachmentOptimal => { ImageLayout::ColorAttachmentOptimal => {
// VUID-vkCmdBeginRenderPass2-initialLayout-03094 // VUID-vkCmdBeginRenderPass2-initialLayout-03094
if !image_view.usage().color_attachment { if !image_view.usage().intersects(ImageUsage::COLOR_ATTACHMENT) {
return Err(RenderPassError::AttachmentImageMissingUsage { return Err(RenderPassError::AttachmentImageMissingUsage {
attachment_index, attachment_index,
usage: "color_attachment", usage: "color_attachment",
@ -167,7 +170,10 @@ where
| ImageLayout::DepthStencilAttachmentOptimal | ImageLayout::DepthStencilAttachmentOptimal
| ImageLayout::DepthStencilReadOnlyOptimal => { | ImageLayout::DepthStencilReadOnlyOptimal => {
// VUID-vkCmdBeginRenderPass2-initialLayout-03096 // VUID-vkCmdBeginRenderPass2-initialLayout-03096
if !image_view.usage().depth_stencil_attachment { if !image_view
.usage()
.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
{
return Err(RenderPassError::AttachmentImageMissingUsage { return Err(RenderPassError::AttachmentImageMissingUsage {
attachment_index, attachment_index,
usage: "depth_stencil_attachment", usage: "depth_stencil_attachment",
@ -176,7 +182,10 @@ where
} }
ImageLayout::ShaderReadOnlyOptimal => { ImageLayout::ShaderReadOnlyOptimal => {
// VUID-vkCmdBeginRenderPass2-initialLayout-03097 // VUID-vkCmdBeginRenderPass2-initialLayout-03097
if !(image_view.usage().sampled || image_view.usage().input_attachment) { if !image_view
.usage()
.intersects(ImageUsage::SAMPLED | ImageUsage::INPUT_ATTACHMENT)
{
return Err(RenderPassError::AttachmentImageMissingUsage { return Err(RenderPassError::AttachmentImageMissingUsage {
attachment_index, attachment_index,
usage: "sampled or input_attachment", usage: "sampled or input_attachment",
@ -185,7 +194,7 @@ where
} }
ImageLayout::TransferSrcOptimal => { ImageLayout::TransferSrcOptimal => {
// VUID-vkCmdBeginRenderPass2-initialLayout-03098 // VUID-vkCmdBeginRenderPass2-initialLayout-03098
if !image_view.usage().transfer_src { if !image_view.usage().intersects(ImageUsage::TRANSFER_SRC) {
return Err(RenderPassError::AttachmentImageMissingUsage { return Err(RenderPassError::AttachmentImageMissingUsage {
attachment_index, attachment_index,
usage: "transfer_src", usage: "transfer_src",
@ -194,7 +203,7 @@ where
} }
ImageLayout::TransferDstOptimal => { ImageLayout::TransferDstOptimal => {
// VUID-vkCmdBeginRenderPass2-initialLayout-03099 // VUID-vkCmdBeginRenderPass2-initialLayout-03099
if !image_view.usage().transfer_dst { if !image_view.usage().intersects(ImageUsage::TRANSFER_DST) {
return Err(RenderPassError::AttachmentImageMissingUsage { return Err(RenderPassError::AttachmentImageMissingUsage {
attachment_index, attachment_index,
usage: "transfer_dst", usage: "transfer_dst",
@ -228,7 +237,7 @@ where
match atch_ref.layout { match atch_ref.layout {
ImageLayout::ColorAttachmentOptimal => { ImageLayout::ColorAttachmentOptimal => {
// VUID-vkCmdBeginRenderPass2-initialLayout-03094 // VUID-vkCmdBeginRenderPass2-initialLayout-03094
if !image_view.usage().color_attachment { if !image_view.usage().intersects(ImageUsage::COLOR_ATTACHMENT) {
return Err(RenderPassError::AttachmentImageMissingUsage { return Err(RenderPassError::AttachmentImageMissingUsage {
attachment_index: atch_ref.attachment, attachment_index: atch_ref.attachment,
usage: "color_attachment", usage: "color_attachment",
@ -240,7 +249,10 @@ where
| ImageLayout::DepthStencilAttachmentOptimal | ImageLayout::DepthStencilAttachmentOptimal
| ImageLayout::DepthStencilReadOnlyOptimal => { | ImageLayout::DepthStencilReadOnlyOptimal => {
// VUID-vkCmdBeginRenderPass2-initialLayout-03096 // VUID-vkCmdBeginRenderPass2-initialLayout-03096
if !image_view.usage().depth_stencil_attachment { if !image_view
.usage()
.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
{
return Err(RenderPassError::AttachmentImageMissingUsage { return Err(RenderPassError::AttachmentImageMissingUsage {
attachment_index: atch_ref.attachment, attachment_index: atch_ref.attachment,
usage: "depth_stencil_attachment", usage: "depth_stencil_attachment",
@ -249,7 +261,10 @@ where
} }
ImageLayout::ShaderReadOnlyOptimal => { ImageLayout::ShaderReadOnlyOptimal => {
// VUID-vkCmdBeginRenderPass2-initialLayout-03097 // VUID-vkCmdBeginRenderPass2-initialLayout-03097
if !(image_view.usage().sampled || image_view.usage().input_attachment) { if !image_view
.usage()
.intersects(ImageUsage::SAMPLED | ImageUsage::INPUT_ATTACHMENT)
{
return Err(RenderPassError::AttachmentImageMissingUsage { return Err(RenderPassError::AttachmentImageMissingUsage {
attachment_index: atch_ref.attachment, attachment_index: atch_ref.attachment,
usage: "sampled or input_attachment", usage: "sampled or input_attachment",
@ -258,7 +273,7 @@ where
} }
ImageLayout::TransferSrcOptimal => { ImageLayout::TransferSrcOptimal => {
// VUID-vkCmdBeginRenderPass2-initialLayout-03098 // VUID-vkCmdBeginRenderPass2-initialLayout-03098
if !image_view.usage().transfer_src { if !image_view.usage().intersects(ImageUsage::TRANSFER_SRC) {
return Err(RenderPassError::AttachmentImageMissingUsage { return Err(RenderPassError::AttachmentImageMissingUsage {
attachment_index: atch_ref.attachment, attachment_index: atch_ref.attachment,
usage: "transfer_src", usage: "transfer_src",
@ -267,7 +282,7 @@ where
} }
ImageLayout::TransferDstOptimal => { ImageLayout::TransferDstOptimal => {
// VUID-vkCmdBeginRenderPass2-initialLayout-03099 // VUID-vkCmdBeginRenderPass2-initialLayout-03099
if !image_view.usage().transfer_dst { if !image_view.usage().intersects(ImageUsage::TRANSFER_DST) {
return Err(RenderPassError::AttachmentImageMissingUsage { return Err(RenderPassError::AttachmentImageMissingUsage {
attachment_index: atch_ref.attachment, attachment_index: atch_ref.attachment,
usage: "transfer_dst", usage: "transfer_dst",
@ -344,9 +359,9 @@ where
} }
} else { } else {
let attachment_aspects = attachment_format.aspects(); let attachment_aspects = attachment_format.aspects();
let need_depth = let need_depth = attachment_aspects.intersects(ImageAspects::DEPTH)
attachment_aspects.depth && attachment_desc.load_op == LoadOp::Clear; && attachment_desc.load_op == LoadOp::Clear;
let need_stencil = attachment_aspects.stencil let need_stencil = attachment_aspects.intersects(ImageAspects::STENCIL)
&& attachment_desc.stencil_load_op == LoadOp::Clear; && attachment_desc.stencil_load_op == LoadOp::Clear;
if need_depth && need_stencil { if need_depth && need_stencil {
@ -456,10 +471,10 @@ where
} }
// VUID-vkCmdNextSubpass2-commandBuffer-cmdpool // VUID-vkCmdNextSubpass2-commandBuffer-cmdpool
debug_assert!({ debug_assert!(self
let queue_family_properties = self.queue_family_properties(); .queue_family_properties()
queue_family_properties.queue_flags.graphics .queue_flags
}); .intersects(QueueFlags::GRAPHICS));
// VUID-vkCmdNextSubpass2-bufferlevel // VUID-vkCmdNextSubpass2-bufferlevel
// Ensured by the type of the impl block // Ensured by the type of the impl block
@ -514,10 +529,10 @@ where
} }
// VUID-vkCmdEndRenderPass2-commandBuffer-cmdpool // VUID-vkCmdEndRenderPass2-commandBuffer-cmdpool
debug_assert!({ debug_assert!(self
let queue_family_properties = self.queue_family_properties(); .queue_family_properties()
queue_family_properties.queue_flags.graphics .queue_flags
}); .intersects(QueueFlags::GRAPHICS));
// VUID-vkCmdEndRenderPass2-bufferlevel // VUID-vkCmdEndRenderPass2-bufferlevel
// Ensured by the type of the impl block // Ensured by the type of the impl block
@ -678,7 +693,7 @@ where
// VUID-vkCmdBeginRendering-dynamicRendering-06446 // VUID-vkCmdBeginRendering-dynamicRendering-06446
if !device.enabled_features().dynamic_rendering { if !device.enabled_features().dynamic_rendering {
return Err(RenderPassError::RequirementNotMet { return Err(RenderPassError::RequirementNotMet {
required_for: "`begin_rendering`", required_for: "`AutoCommandBufferBuilder::begin_rendering`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["dynamic_rendering"], features: &["dynamic_rendering"],
..Default::default() ..Default::default()
@ -689,7 +704,10 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdBeginRendering-commandBuffer-cmdpool // VUID-vkCmdBeginRendering-commandBuffer-cmdpool
if !queue_family_properties.queue_flags.graphics { if !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS)
{
return Err(RenderPassError::NotSupportedByQueueFamily); return Err(RenderPassError::NotSupportedByQueueFamily);
} }
@ -785,7 +803,7 @@ where
store_op.validate_device(device)?; store_op.validate_device(device)?;
// VUID-VkRenderingInfo-colorAttachmentCount-06087 // VUID-VkRenderingInfo-colorAttachmentCount-06087
if !image_view.usage().color_attachment { if !image_view.usage().intersects(ImageUsage::COLOR_ATTACHMENT) {
return Err(RenderPassError::ColorAttachmentMissingUsage { attachment_index }); return Err(RenderPassError::ColorAttachmentMissingUsage { attachment_index });
} }
@ -942,12 +960,15 @@ where
let image_aspects = image_view.format().unwrap().aspects(); let image_aspects = image_view.format().unwrap().aspects();
// VUID-VkRenderingInfo-pDepthAttachment-06547 // VUID-VkRenderingInfo-pDepthAttachment-06547
if !image_aspects.depth { if !image_aspects.intersects(ImageAspects::DEPTH) {
return Err(RenderPassError::DepthAttachmentFormatUsageNotSupported); return Err(RenderPassError::DepthAttachmentFormatUsageNotSupported);
} }
// VUID-VkRenderingInfo-pDepthAttachment-06088 // VUID-VkRenderingInfo-pDepthAttachment-06088
if !image_view.usage().depth_stencil_attachment { if !image_view
.usage()
.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
{
return Err(RenderPassError::DepthAttachmentMissingUsage); return Err(RenderPassError::DepthAttachmentMissingUsage);
} }
@ -1003,7 +1024,7 @@ where
// VUID-VkRenderingInfo-pDepthAttachment-06102 // VUID-VkRenderingInfo-pDepthAttachment-06102
if !properties if !properties
.supported_depth_resolve_modes .supported_depth_resolve_modes
.map_or(false, |modes| modes.contains_mode(mode)) .map_or(false, |modes| modes.contains_enum(mode))
{ {
return Err(RenderPassError::DepthAttachmentResolveModeNotSupported); return Err(RenderPassError::DepthAttachmentResolveModeNotSupported);
} }
@ -1069,12 +1090,15 @@ where
let image_aspects = image_view.format().unwrap().aspects(); let image_aspects = image_view.format().unwrap().aspects();
// VUID-VkRenderingInfo-pStencilAttachment-06548 // VUID-VkRenderingInfo-pStencilAttachment-06548
if !image_aspects.stencil { if !image_aspects.intersects(ImageAspects::STENCIL) {
return Err(RenderPassError::StencilAttachmentFormatUsageNotSupported); return Err(RenderPassError::StencilAttachmentFormatUsageNotSupported);
} }
// VUID-VkRenderingInfo-pStencilAttachment-06089 // VUID-VkRenderingInfo-pStencilAttachment-06089
if !image_view.usage().depth_stencil_attachment { if !image_view
.usage()
.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
{
return Err(RenderPassError::StencilAttachmentMissingUsage); return Err(RenderPassError::StencilAttachmentMissingUsage);
} }
@ -1130,7 +1154,7 @@ where
// VUID-VkRenderingInfo-pStencilAttachment-06103 // VUID-VkRenderingInfo-pStencilAttachment-06103
if !properties if !properties
.supported_stencil_resolve_modes .supported_stencil_resolve_modes
.map_or(false, |modes| modes.contains_mode(mode)) .map_or(false, |modes| modes.contains_enum(mode))
{ {
return Err(RenderPassError::StencilAttachmentResolveModeNotSupported); return Err(RenderPassError::StencilAttachmentResolveModeNotSupported);
} }
@ -1251,10 +1275,10 @@ where
} }
// VUID-vkCmdEndRendering-commandBuffer-cmdpool // VUID-vkCmdEndRendering-commandBuffer-cmdpool
debug_assert!({ debug_assert!(self
let queue_family_properties = self.queue_family_properties(); .queue_family_properties()
queue_family_properties.queue_flags.graphics .queue_flags
}); .intersects(QueueFlags::GRAPHICS));
Ok(()) Ok(())
} }
@ -1416,8 +1440,9 @@ where
if matches!( if matches!(
clear_attachment, clear_attachment,
ClearAttachment::Depth(_) | ClearAttachment::DepthStencil(_) ClearAttachment::Depth(_) | ClearAttachment::DepthStencil(_)
) && !depth_format.map_or(false, |format| format.aspects().depth) ) && !depth_format.map_or(false, |format| {
{ format.aspects().intersects(ImageAspects::DEPTH)
}) {
return Err(RenderPassError::ClearAttachmentNotCompatible { return Err(RenderPassError::ClearAttachmentNotCompatible {
clear_attachment, clear_attachment,
attachment_format: None, attachment_format: None,
@ -1428,8 +1453,9 @@ where
if matches!( if matches!(
clear_attachment, clear_attachment,
ClearAttachment::Stencil(_) | ClearAttachment::DepthStencil(_) ClearAttachment::Stencil(_) | ClearAttachment::DepthStencil(_)
) && !stencil_format.map_or(false, |format| format.aspects().stencil) ) && !stencil_format.map_or(false, |format| {
{ format.aspects().intersects(ImageAspects::STENCIL)
}) {
return Err(RenderPassError::ClearAttachmentNotCompatible { return Err(RenderPassError::ClearAttachmentNotCompatible {
clear_attachment, clear_attachment,
attachment_format: None, attachment_format: None,
@ -1502,10 +1528,10 @@ where
} }
// VUID-vkCmdClearAttachments-commandBuffer-cmdpool // VUID-vkCmdClearAttachments-commandBuffer-cmdpool
debug_assert!({ debug_assert!(self
let queue_family_properties = self.queue_family_properties(); .queue_family_properties()
queue_family_properties.queue_flags.graphics .queue_flags
}); .intersects(QueueFlags::GRAPHICS));
Ok(()) Ok(())
} }
@ -1559,18 +1585,12 @@ impl SyncCommandBufferBuilder {
image: image_view.image(), image: image_view.image(),
subresource_range: image_view.subresource_range().clone(), subresource_range: image_view.subresource_range().clone(),
memory: PipelineMemoryAccess { memory: PipelineMemoryAccess {
stages: PipelineStages { stages: PipelineStages::ALL_COMMANDS, // TODO: wrong!
all_commands: true, access: AccessFlags::INPUT_ATTACHMENT_READ
..PipelineStages::empty() | AccessFlags::COLOR_ATTACHMENT_READ
}, // TODO: wrong! | AccessFlags::COLOR_ATTACHMENT_WRITE
access: AccessFlags { | AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ
input_attachment_read: true, | AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE, // TODO: suboptimal
color_attachment_read: true,
color_attachment_write: true,
depth_stencil_attachment_read: true,
depth_stencil_attachment_write: true,
..AccessFlags::empty()
}, // TODO: suboptimal
exclusive: true, // TODO: suboptimal ; note: remember to always pass true if desc.initial_layout != desc.final_layout exclusive: true, // TODO: suboptimal ; note: remember to always pass true if desc.initial_layout != desc.final_layout
}, },
start_layout: desc.initial_layout, start_layout: desc.initial_layout,
@ -1696,16 +1716,10 @@ impl SyncCommandBufferBuilder {
image: image_view.image(), image: image_view.image(),
subresource_range: image_view.subresource_range().clone(), subresource_range: image_view.subresource_range().clone(),
memory: PipelineMemoryAccess { memory: PipelineMemoryAccess {
stages: PipelineStages { stages: PipelineStages::ALL_COMMANDS, // TODO: wrong!
all_commands: true, access: AccessFlags::COLOR_ATTACHMENT_READ
..PipelineStages::empty() | AccessFlags::COLOR_ATTACHMENT_WRITE, // TODO: suboptimal
}, // TODO: wrong! exclusive: true, // TODO: suboptimal
access: AccessFlags {
color_attachment_read: true,
color_attachment_write: true,
..AccessFlags::empty()
}, // TODO: suboptimal
exclusive: true, // TODO: suboptimal
}, },
start_layout: image_layout, start_layout: image_layout,
end_layout: image_layout, end_layout: image_layout,
@ -1724,16 +1738,10 @@ impl SyncCommandBufferBuilder {
image: image_view.image(), image: image_view.image(),
subresource_range: image_view.subresource_range().clone(), subresource_range: image_view.subresource_range().clone(),
memory: PipelineMemoryAccess { memory: PipelineMemoryAccess {
stages: PipelineStages { stages: PipelineStages::ALL_COMMANDS, // TODO: wrong!
all_commands: true, access: AccessFlags::COLOR_ATTACHMENT_READ
..PipelineStages::empty() | AccessFlags::COLOR_ATTACHMENT_WRITE, // TODO: suboptimal
}, // TODO: wrong! exclusive: true, // TODO: suboptimal
access: AccessFlags {
color_attachment_read: true,
color_attachment_write: true,
..AccessFlags::empty()
}, // TODO: suboptimal
exclusive: true, // TODO: suboptimal
}, },
start_layout: image_layout, start_layout: image_layout,
end_layout: image_layout, end_layout: image_layout,
@ -1762,16 +1770,10 @@ impl SyncCommandBufferBuilder {
image: image_view.image(), image: image_view.image(),
subresource_range: image_view.subresource_range().clone(), subresource_range: image_view.subresource_range().clone(),
memory: PipelineMemoryAccess { memory: PipelineMemoryAccess {
stages: PipelineStages { stages: PipelineStages::ALL_COMMANDS, // TODO: wrong!
all_commands: true, access: AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ
..PipelineStages::empty() | AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE, // TODO: suboptimal
}, // TODO: wrong! exclusive: true, // TODO: suboptimal
access: AccessFlags {
depth_stencil_attachment_read: true,
depth_stencil_attachment_write: true,
..AccessFlags::empty()
}, // TODO: suboptimal
exclusive: true, // TODO: suboptimal
}, },
start_layout: image_layout, start_layout: image_layout,
end_layout: image_layout, end_layout: image_layout,
@ -1790,15 +1792,9 @@ impl SyncCommandBufferBuilder {
image: image_view.image(), image: image_view.image(),
subresource_range: image_view.subresource_range().clone(), subresource_range: image_view.subresource_range().clone(),
memory: PipelineMemoryAccess { memory: PipelineMemoryAccess {
stages: PipelineStages { stages: PipelineStages::ALL_COMMANDS, // TODO: wrong!
all_commands: true, access: AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ
..PipelineStages::empty() | AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE, // TODO: suboptimal
}, // TODO: wrong!
access: AccessFlags {
depth_stencil_attachment_read: true,
depth_stencil_attachment_write: true,
..AccessFlags::empty()
}, // TODO: suboptimal
exclusive: true, // TODO: suboptimal exclusive: true, // TODO: suboptimal
}, },
start_layout: image_layout, start_layout: image_layout,
@ -1828,16 +1824,10 @@ impl SyncCommandBufferBuilder {
image: image_view.image(), image: image_view.image(),
subresource_range: image_view.subresource_range().clone(), subresource_range: image_view.subresource_range().clone(),
memory: PipelineMemoryAccess { memory: PipelineMemoryAccess {
stages: PipelineStages { stages: PipelineStages::ALL_COMMANDS, // TODO: wrong!
all_commands: true, access: AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ
..PipelineStages::empty() | AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE, // TODO: suboptimal
}, // TODO: wrong! exclusive: true, // TODO: suboptimal
access: AccessFlags {
depth_stencil_attachment_read: true,
depth_stencil_attachment_write: true,
..AccessFlags::empty()
}, // TODO: suboptimal
exclusive: true, // TODO: suboptimal
}, },
start_layout: image_layout, start_layout: image_layout,
end_layout: image_layout, end_layout: image_layout,
@ -1856,15 +1846,9 @@ impl SyncCommandBufferBuilder {
image: image_view.image(), image: image_view.image(),
subresource_range: image_view.subresource_range().clone(), subresource_range: image_view.subresource_range().clone(),
memory: PipelineMemoryAccess { memory: PipelineMemoryAccess {
stages: PipelineStages { stages: PipelineStages::ALL_COMMANDS, // TODO: wrong!
all_commands: true, access: AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ
..PipelineStages::empty() | AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE, // TODO: suboptimal
}, // TODO: wrong!
access: AccessFlags {
depth_stencil_attachment_read: true,
depth_stencil_attachment_write: true,
..AccessFlags::empty()
}, // TODO: suboptimal
exclusive: true, // TODO: suboptimal exclusive: true, // TODO: suboptimal
}, },
start_layout: image_layout, start_layout: image_layout,
@ -2429,7 +2413,7 @@ impl RenderingAttachmentInfo {
#[inline] #[inline]
pub fn image_view(image_view: Arc<dyn ImageViewAbstract>) -> Self { pub fn image_view(image_view: Arc<dyn ImageViewAbstract>) -> Self {
let aspects = image_view.format().unwrap().aspects(); let aspects = image_view.format().unwrap().aspects();
let image_layout = if aspects.depth || aspects.stencil { let image_layout = if aspects.intersects(ImageAspects::DEPTH | ImageAspects::STENCIL) {
ImageLayout::DepthStencilAttachmentOptimal ImageLayout::DepthStencilAttachmentOptimal
} else { } else {
ImageLayout::ColorAttachmentOptimal ImageLayout::ColorAttachmentOptimal
@ -2473,7 +2457,7 @@ impl RenderingAttachmentResolveInfo {
#[inline] #[inline]
pub fn image_view(image_view: Arc<dyn ImageViewAbstract>) -> Self { pub fn image_view(image_view: Arc<dyn ImageViewAbstract>) -> Self {
let aspects = image_view.format().unwrap().aspects(); let aspects = image_view.format().unwrap().aspects();
let image_layout = if aspects.depth || aspects.stencil { let image_layout = if aspects.intersects(ImageAspects::DEPTH | ImageAspects::STENCIL) {
ImageLayout::DepthStencilAttachmentOptimal ImageLayout::DepthStencilAttachmentOptimal
} else { } else {
ImageLayout::ColorAttachmentOptimal ImageLayout::ColorAttachmentOptimal

View File

@ -16,7 +16,7 @@ use crate::{
AutoCommandBufferBuilder, CommandBufferExecError, CommandBufferInheritanceRenderPassType, AutoCommandBufferBuilder, CommandBufferExecError, CommandBufferInheritanceRenderPassType,
CommandBufferUsage, SecondaryCommandBufferAbstract, SubpassContents, CommandBufferUsage, SecondaryCommandBufferAbstract, SubpassContents,
}, },
device::DeviceOwned, device::{DeviceOwned, QueueFlags},
format::Format, format::Format,
image::SampleCount, image::SampleCount,
query::{QueryControlFlags, QueryPipelineStatisticFlags, QueryType}, query::{QueryControlFlags, QueryPipelineStatisticFlags, QueryType},
@ -119,9 +119,9 @@ where
let queue_family_properties = self.queue_family_properties(); let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdExecuteCommands-commandBuffer-cmdpool // VUID-vkCmdExecuteCommands-commandBuffer-cmdpool
if !(queue_family_properties.queue_flags.transfer if !queue_family_properties
|| queue_family_properties.queue_flags.graphics .queue_flags
|| queue_family_properties.queue_flags.compute) .intersects(QueueFlags::TRANSFER | QueueFlags::GRAPHICS | QueueFlags::COMPUTE)
{ {
return Err(ExecuteCommandsError::NotSupportedByQueueFamily); return Err(ExecuteCommandsError::NotSupportedByQueueFamily);
} }
@ -325,7 +325,7 @@ where
// VUID-vkCmdExecuteCommands-commandBuffer-00101 // VUID-vkCmdExecuteCommands-commandBuffer-00101
if !self.query_state.is_empty() && !self.device().enabled_features().inherited_queries { if !self.query_state.is_empty() && !self.device().enabled_features().inherited_queries {
return Err(ExecuteCommandsError::RequirementNotMet { return Err(ExecuteCommandsError::RequirementNotMet {
required_for: "`execute_commands` when a query is active", required_for: "`AutoCommandBufferBuilder::execute_commands` when a query is active",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["inherited_queries"], features: &["inherited_queries"],
..Default::default() ..Default::default()

View File

@ -126,8 +126,8 @@ impl UnsafeCommandBufferBuilder {
_ne: _, _ne: _,
} = barrier; } = barrier;
debug_assert!(src_stages.supported_access().contains(&src_access)); debug_assert!(src_stages.supported_access().contains(src_access));
debug_assert!(dst_stages.supported_access().contains(&dst_access)); debug_assert!(dst_stages.supported_access().contains(dst_access));
ash::vk::MemoryBarrier2 { ash::vk::MemoryBarrier2 {
src_stage_mask: src_stages.into(), src_stage_mask: src_stages.into(),
@ -153,8 +153,8 @@ impl UnsafeCommandBufferBuilder {
_ne: _, _ne: _,
} = barrier; } = barrier;
debug_assert!(src_stages.supported_access().contains(&src_access)); debug_assert!(src_stages.supported_access().contains(src_access));
debug_assert!(dst_stages.supported_access().contains(&dst_access)); debug_assert!(dst_stages.supported_access().contains(dst_access));
debug_assert!(!range.is_empty()); debug_assert!(!range.is_empty());
debug_assert!(range.end <= buffer.size()); debug_assert!(range.end <= buffer.size());
@ -195,8 +195,8 @@ impl UnsafeCommandBufferBuilder {
_ne: _, _ne: _,
} = barrier; } = barrier;
debug_assert!(src_stages.supported_access().contains(&src_access)); debug_assert!(src_stages.supported_access().contains(src_access));
debug_assert!(dst_stages.supported_access().contains(&dst_access)); debug_assert!(dst_stages.supported_access().contains(dst_access));
debug_assert!(!matches!( debug_assert!(!matches!(
new_layout, new_layout,
ImageLayout::Undefined | ImageLayout::Preinitialized ImageLayout::Undefined | ImageLayout::Preinitialized
@ -205,7 +205,7 @@ impl UnsafeCommandBufferBuilder {
.format() .format()
.unwrap() .unwrap()
.aspects() .aspects()
.contains(&subresource_range.aspects)); .contains(subresource_range.aspects));
debug_assert!(!subresource_range.mip_levels.is_empty()); debug_assert!(!subresource_range.mip_levels.is_empty());
debug_assert!(subresource_range.mip_levels.end <= image.mip_levels()); debug_assert!(subresource_range.mip_levels.end <= image.mip_levels());
debug_assert!(!subresource_range.array_layers.is_empty()); debug_assert!(!subresource_range.array_layers.is_empty());
@ -272,8 +272,8 @@ impl UnsafeCommandBufferBuilder {
_ne: _, _ne: _,
} = barrier; } = barrier;
debug_assert!(src_stages.supported_access().contains(&src_access)); debug_assert!(src_stages.supported_access().contains(src_access));
debug_assert!(dst_stages.supported_access().contains(&dst_access)); debug_assert!(dst_stages.supported_access().contains(dst_access));
src_stage_mask |= src_stages.into(); src_stage_mask |= src_stages.into();
dst_stage_mask |= dst_stages.into(); dst_stage_mask |= dst_stages.into();
@ -300,8 +300,8 @@ impl UnsafeCommandBufferBuilder {
_ne: _, _ne: _,
} = barrier; } = barrier;
debug_assert!(src_stages.supported_access().contains(&src_access)); debug_assert!(src_stages.supported_access().contains(src_access));
debug_assert!(dst_stages.supported_access().contains(&dst_access)); debug_assert!(dst_stages.supported_access().contains(dst_access));
debug_assert!(!range.is_empty()); debug_assert!(!range.is_empty());
debug_assert!(range.end <= buffer.size()); debug_assert!(range.end <= buffer.size());
@ -343,8 +343,8 @@ impl UnsafeCommandBufferBuilder {
_ne: _, _ne: _,
} = barrier; } = barrier;
debug_assert!(src_stages.supported_access().contains(&src_access)); debug_assert!(src_stages.supported_access().contains(src_access));
debug_assert!(dst_stages.supported_access().contains(&dst_access)); debug_assert!(dst_stages.supported_access().contains(dst_access));
debug_assert!(!matches!( debug_assert!(!matches!(
new_layout, new_layout,
ImageLayout::Undefined | ImageLayout::Preinitialized ImageLayout::Undefined | ImageLayout::Preinitialized
@ -353,7 +353,7 @@ impl UnsafeCommandBufferBuilder {
.format() .format()
.unwrap() .unwrap()
.aspects() .aspects()
.contains(&subresource_range.aspects)); .contains(subresource_range.aspects));
debug_assert!(!subresource_range.mip_levels.is_empty()); debug_assert!(!subresource_range.mip_levels.is_empty());
debug_assert!(subresource_range.mip_levels.end <= image.mip_levels()); debug_assert!(subresource_range.mip_levels.end <= image.mip_levels());
debug_assert!(!subresource_range.array_layers.is_empty()); debug_assert!(!subresource_range.array_layers.is_empty());
@ -895,7 +895,7 @@ impl UnsafeCommandBufferBuilder {
/// Calls `vkCmdResetEvent` on the builder. /// Calls `vkCmdResetEvent` on the builder.
#[inline] #[inline]
pub unsafe fn reset_event(&mut self, event: &Event, stages: PipelineStages) { pub unsafe fn reset_event(&mut self, event: &Event, stages: PipelineStages) {
debug_assert!(!stages.host); debug_assert!(!stages.intersects(PipelineStages::HOST));
debug_assert_ne!(stages, PipelineStages::empty()); debug_assert_ne!(stages, PipelineStages::empty());
let fns = self.device.fns(); let fns = self.device.fns();

File diff suppressed because it is too large Load Diff

View File

@ -169,8 +169,9 @@ pub struct DispatchIndirectCommand {
} }
vulkan_enum! { vulkan_enum! {
/// Describes what a subpass in a command buffer will contain.
#[non_exhaustive] #[non_exhaustive]
/// Describes what a subpass in a command buffer will contain.
SubpassContents = SubpassContents(i32); SubpassContents = SubpassContents(i32);
/// The subpass will only directly contain commands. /// The subpass will only directly contain commands.
@ -229,10 +230,12 @@ pub struct CommandBufferInheritanceInfo {
/// Which pipeline statistics queries are allowed to be active on the primary command buffer /// Which pipeline statistics queries are allowed to be active on the primary command buffer
/// when this secondary command buffer is executed. /// when this secondary command buffer is executed.
/// ///
/// The `pipeline_statistics_query` feature must be enabled if any of the flags of this value /// If this value is not empty, the [`pipeline_statistics_query`] feature must be enabled on
/// are set. /// the device.
/// ///
/// The default value is [`QueryPipelineStatisticFlags::empty()`]. /// The default value is [`QueryPipelineStatisticFlags::empty()`].
///
/// [`pipeline_statistics_query`]: crate::device::Features::pipeline_statistics_query
pub query_statistics_flags: QueryPipelineStatisticFlags, pub query_statistics_flags: QueryPipelineStatisticFlags,
pub _ne: crate::NonExhaustive, pub _ne: crate::NonExhaustive,
@ -326,10 +329,11 @@ pub struct CommandBufferInheritanceRenderingInfo {
/// indices that are rendered to. The value is a bitmask, so that that for example `0b11` will /// indices that are rendered to. The value is a bitmask, so that that for example `0b11` will
/// draw to the first two views and `0b101` will draw to the first and third view. /// draw to the first two views and `0b101` will draw to the first and third view.
/// ///
/// If set to a nonzero value, the [`multiview`](crate::device::Features::multiview) feature /// If set to a nonzero value, then the [`multiview`] feature must be enabled on the device.
/// must be enabled on the device.
/// ///
/// The default value is `0`. /// The default value is `0`.
///
/// [`multiview`]: crate::device::Features::multiview
pub view_mask: u32, pub view_mask: u32,
/// The formats of the color attachments that will be used during rendering. /// The formats of the color attachments that will be used during rendering.
@ -449,11 +453,13 @@ pub struct SemaphoreSubmitInfo {
/// For a semaphore signal operation, specifies the pipeline stages in the first synchronization /// For a semaphore signal operation, specifies the pipeline stages in the first synchronization
/// scope: stages of queue operations preceding the signal operation that must complete before /// scope: stages of queue operations preceding the signal operation that must complete before
/// the semaphore is signalled. /// the semaphore is signalled.
/// If not set to `all_commands` only, the /// If this value does not equal [`ALL_COMMANDS`], then the [`synchronization2`] feature must
/// [`synchronization2`](crate::device::Features::synchronization2) feature must be enabled /// be enabled on the device.
/// on the device.
/// ///
/// The default value has only `all_commands` set. /// The default value is [`ALL_COMMANDS`].
///
/// [`ALL_COMMANDS`]: PipelineStages::ALL_COMMANDS
/// [`synchronization2`]: crate::device::Features::synchronization2
pub stages: PipelineStages, pub stages: PipelineStages,
pub _ne: crate::NonExhaustive, pub _ne: crate::NonExhaustive,
@ -465,10 +471,7 @@ impl SemaphoreSubmitInfo {
pub fn semaphore(semaphore: Arc<Semaphore>) -> Self { pub fn semaphore(semaphore: Arc<Semaphore>) -> Self {
Self { Self {
semaphore, semaphore,
stages: PipelineStages { stages: PipelineStages::ALL_COMMANDS,
all_commands: true,
..PipelineStages::empty()
},
_ne: crate::NonExhaustive(()), _ne: crate::NonExhaustive(()),
} }
} }

View File

@ -276,7 +276,7 @@ impl CommandPool {
|| self.device.enabled_extensions().khr_maintenance1) || self.device.enabled_extensions().khr_maintenance1)
{ {
return Err(CommandPoolTrimError::RequirementNotMet { return Err(CommandPoolTrimError::RequirementNotMet {
required_for: "`trim`", required_for: "`CommandPool::trim`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
api_version: Some(Version::V1_1), api_version: Some(Version::V1_1),
device_extensions: &["khr_maintenance1"], device_extensions: &["khr_maintenance1"],

View File

@ -205,7 +205,7 @@ impl SyncCommandBufferBuilder {
ref range, ref range,
ref memory, ref memory,
} => { } => {
debug_assert!(memory.stages.supported_access().contains(&memory.access)); debug_assert!(memory.stages.supported_access().contains(memory.access));
if let Some(conflicting_use) = if let Some(conflicting_use) =
self.find_buffer_conflict(buffer, range.clone(), memory) self.find_buffer_conflict(buffer, range.clone(), memory)
@ -226,7 +226,7 @@ impl SyncCommandBufferBuilder {
end_layout, end_layout,
} => { } => {
debug_assert!(memory.exclusive || start_layout == end_layout); debug_assert!(memory.exclusive || start_layout == end_layout);
debug_assert!(memory.stages.supported_access().contains(&memory.access)); debug_assert!(memory.stages.supported_access().contains(memory.access));
debug_assert!(end_layout != ImageLayout::Undefined); debug_assert!(end_layout != ImageLayout::Undefined);
debug_assert!(end_layout != ImageLayout::Preinitialized); debug_assert!(end_layout != ImageLayout::Preinitialized);
@ -453,24 +453,10 @@ impl SyncCommandBufferBuilder {
// will come before them, it's the only thing that works for now. // will come before them, it's the only thing that works for now.
// TODO: come up with something better // TODO: come up with something better
let barrier = BufferMemoryBarrier { let barrier = BufferMemoryBarrier {
src_stages: PipelineStages { src_stages: PipelineStages::ALL_COMMANDS,
all_commands: true, src_access: AccessFlags::MEMORY_READ | AccessFlags::MEMORY_WRITE,
..PipelineStages::empty() dst_stages: PipelineStages::ALL_COMMANDS,
}, dst_access: AccessFlags::MEMORY_READ | AccessFlags::MEMORY_WRITE,
src_access: AccessFlags {
memory_read: true,
memory_write: true,
..AccessFlags::empty()
},
dst_stages: PipelineStages {
all_commands: true,
..PipelineStages::empty()
},
dst_access: AccessFlags {
memory_read: true,
memory_write: true,
..AccessFlags::empty()
},
range: range.clone(), range: range.clone(),
..BufferMemoryBarrier::buffer(inner.buffer.clone()) ..BufferMemoryBarrier::buffer(inner.buffer.clone())
}; };
@ -644,24 +630,10 @@ impl SyncCommandBufferBuilder {
// will come before them, it's the only thing that works for now. // will come before them, it's the only thing that works for now.
// TODO: come up with something better // TODO: come up with something better
let mut barrier = ImageMemoryBarrier { let mut barrier = ImageMemoryBarrier {
src_stages: PipelineStages { src_stages: PipelineStages::ALL_COMMANDS,
all_commands: true, src_access: AccessFlags::MEMORY_READ | AccessFlags::MEMORY_WRITE,
..PipelineStages::empty() dst_stages: PipelineStages::ALL_COMMANDS,
}, dst_access: AccessFlags::MEMORY_READ | AccessFlags::MEMORY_WRITE,
src_access: AccessFlags {
memory_read: true,
memory_write: true,
..AccessFlags::empty()
},
dst_stages: PipelineStages {
all_commands: true,
..PipelineStages::empty()
},
dst_access: AccessFlags {
memory_read: true,
memory_write: true,
..AccessFlags::empty()
},
old_layout: state.initial_layout, old_layout: state.initial_layout,
new_layout: state.initial_layout, new_layout: state.initial_layout,
subresource_range: inner.image.range_to_subresources(range.clone()), subresource_range: inner.image.range_to_subresources(range.clone()),
@ -812,10 +784,7 @@ impl SyncCommandBufferBuilder {
.push(ImageMemoryBarrier { .push(ImageMemoryBarrier {
src_stages: state.memory.stages, src_stages: state.memory.stages,
src_access: state.memory.access, src_access: state.memory.access,
dst_stages: PipelineStages { dst_stages: PipelineStages::TOP_OF_PIPE,
top_of_pipe: true,
..PipelineStages::empty()
},
dst_access: AccessFlags::empty(), dst_access: AccessFlags::empty(),
old_layout: state.current_layout, old_layout: state.current_layout,
new_layout: state.final_layout, new_layout: state.final_layout,

View File

@ -427,10 +427,7 @@ mod tests {
let buffer = DeviceLocalBuffer::from_data( let buffer = DeviceLocalBuffer::from_data(
&memory_allocator, &memory_allocator,
0u32, 0u32,
BufferUsage { BufferUsage::TRANSFER_DST,
transfer_dst: true,
..BufferUsage::empty()
},
&mut cbb, &mut cbb,
) )
.unwrap(); .unwrap();
@ -542,10 +539,7 @@ mod tests {
let memory_allocator = StandardMemoryAllocator::new_default(device); let memory_allocator = StandardMemoryAllocator::new_default(device);
let buf = CpuAccessibleBuffer::from_data( let buf = CpuAccessibleBuffer::from_data(
&memory_allocator, &memory_allocator,
BufferUsage { BufferUsage::VERTEX_BUFFER,
vertex_buffer: true,
..BufferUsage::empty()
},
false, false,
0u32, 0u32,
) )

View File

@ -20,6 +20,7 @@ use crate::{
CommandBufferInheritanceRenderingInfo, CommandBufferInheritanceRenderingInfo,
}, },
device::{Device, DeviceOwned}, device::{Device, DeviceOwned},
query::QueryControlFlags,
OomError, VulkanError, VulkanObject, OomError, VulkanError, VulkanObject,
}; };
use smallvec::SmallVec; use smallvec::SmallVec;
@ -104,7 +105,7 @@ impl UnsafeCommandBufferBuilder {
if let Some(flags) = occlusion_query { if let Some(flags) = occlusion_query {
inheritance_info_vk.occlusion_query_enable = ash::vk::TRUE; inheritance_info_vk.occlusion_query_enable = ash::vk::TRUE;
if flags.precise { if flags.intersects(QueryControlFlags::PRECISE) {
inheritance_info_vk.query_flags = ash::vk::QueryControlFlags::PRECISE; inheritance_info_vk.query_flags = ash::vk::QueryControlFlags::PRECISE;
} }
} }

View File

@ -335,11 +335,8 @@ where
.into_iter() .into_iter()
.map(|semaphore| { .map(|semaphore| {
SemaphoreSubmitInfo { SemaphoreSubmitInfo {
stages: PipelineStages { // TODO: correct stages ; hard
// TODO: correct stages ; hard stages: PipelineStages::ALL_COMMANDS,
all_commands: true,
..PipelineStages::empty()
},
..SemaphoreSubmitInfo::semaphore(semaphore) ..SemaphoreSubmitInfo::semaphore(semaphore)
} }
}) })

View File

@ -221,7 +221,8 @@ impl DescriptorSetLayout {
.descriptor_binding_variable_descriptor_count .descriptor_binding_variable_descriptor_count
{ {
return Err(DescriptorSetLayoutCreationError::RequirementNotMet { return Err(DescriptorSetLayoutCreationError::RequirementNotMet {
required_for: "`create_info.bindings` has an element where `variable_descriptor_count` is set", required_for: "`create_info.bindings` has an element where \
`variable_descriptor_count` is set",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["descriptor_binding_variable_descriptor_count"], features: &["descriptor_binding_variable_descriptor_count"],
..Default::default() ..Default::default()
@ -756,7 +757,7 @@ impl DescriptorSetLayoutBinding {
} }
} }
if !self.stages.contains(&stages) { if !self.stages.contains(stages) {
return Err(DescriptorRequirementsNotMet::ShaderStages { return Err(DescriptorRequirementsNotMet::ShaderStages {
required: stages, required: stages,
obtained: self.stages, obtained: self.stages,
@ -824,8 +825,9 @@ impl Display for DescriptorRequirementsNotMet {
} }
vulkan_enum! { vulkan_enum! {
/// Describes what kind of resource may later be bound to a descriptor.
#[non_exhaustive] #[non_exhaustive]
/// Describes what kind of resource may later be bound to a descriptor.
DescriptorType = DescriptorType(i32); DescriptorType = DescriptorType(i32);
/// Describes how a `SampledImage` descriptor should be read. /// Describes how a `SampledImage` descriptor should be read.

View File

@ -9,9 +9,9 @@
use super::layout::{DescriptorSetLayout, DescriptorSetLayoutBinding, DescriptorType}; use super::layout::{DescriptorSetLayout, DescriptorSetLayoutBinding, DescriptorType};
use crate::{ use crate::{
buffer::{view::BufferViewAbstract, BufferAccess, BufferInner}, buffer::{view::BufferViewAbstract, BufferAccess, BufferInner, BufferUsage},
device::DeviceOwned, device::DeviceOwned,
image::{view::ImageViewType, ImageType, ImageViewAbstract}, image::{view::ImageViewType, ImageAspects, ImageType, ImageUsage, ImageViewAbstract},
sampler::{Sampler, SamplerImageViewIncompatibleError}, sampler::{Sampler, SamplerImageViewIncompatibleError},
DeviceSize, RequiresOneOf, VulkanObject, DeviceSize, RequiresOneOf, VulkanObject,
}; };
@ -425,7 +425,7 @@ pub(crate) fn check_descriptor_write<'a>(
for (index, buffer) in elements.iter().enumerate() { for (index, buffer) in elements.iter().enumerate() {
assert_eq!(device, buffer.device()); assert_eq!(device, buffer.device());
if !buffer.inner().buffer.usage().storage_buffer { if !buffer.usage().intersects(BufferUsage::STORAGE_BUFFER) {
return Err(DescriptorSetUpdateError::MissingUsage { return Err(DescriptorSetUpdateError::MissingUsage {
binding: write.binding(), binding: write.binding(),
index: descriptor_range_start + index as u32, index: descriptor_range_start + index as u32,
@ -438,7 +438,7 @@ pub(crate) fn check_descriptor_write<'a>(
for (index, buffer) in elements.iter().enumerate() { for (index, buffer) in elements.iter().enumerate() {
assert_eq!(device, buffer.device()); assert_eq!(device, buffer.device());
if !buffer.inner().buffer.usage().uniform_buffer { if !buffer.usage().intersects(BufferUsage::UNIFORM_BUFFER) {
return Err(DescriptorSetUpdateError::MissingUsage { return Err(DescriptorSetUpdateError::MissingUsage {
binding: write.binding(), binding: write.binding(),
index: descriptor_range_start + index as u32, index: descriptor_range_start + index as u32,
@ -474,10 +474,8 @@ pub(crate) fn check_descriptor_write<'a>(
// TODO: storage_texel_buffer_atomic // TODO: storage_texel_buffer_atomic
if !buffer_view if !buffer_view
.buffer() .buffer()
.inner()
.buffer
.usage() .usage()
.storage_texel_buffer .intersects(BufferUsage::STORAGE_TEXEL_BUFFER)
{ {
return Err(DescriptorSetUpdateError::MissingUsage { return Err(DescriptorSetUpdateError::MissingUsage {
binding: write.binding(), binding: write.binding(),
@ -493,10 +491,8 @@ pub(crate) fn check_descriptor_write<'a>(
if !buffer_view if !buffer_view
.buffer() .buffer()
.inner()
.buffer
.usage() .usage()
.uniform_texel_buffer .intersects(BufferUsage::UNIFORM_TEXEL_BUFFER)
{ {
return Err(DescriptorSetUpdateError::MissingUsage { return Err(DescriptorSetUpdateError::MissingUsage {
binding: write.binding(), binding: write.binding(),
@ -526,7 +522,7 @@ pub(crate) fn check_descriptor_write<'a>(
assert_eq!(device, image_view.device()); assert_eq!(device, image_view.device());
// VUID-VkWriteDescriptorSet-descriptorType-00337 // VUID-VkWriteDescriptorSet-descriptorType-00337
if !image_view.usage().sampled { if !image_view.usage().intersects(ImageUsage::SAMPLED) {
return Err(DescriptorSetUpdateError::MissingUsage { return Err(DescriptorSetUpdateError::MissingUsage {
binding: write.binding(), binding: write.binding(),
index: descriptor_range_start + index as u32, index: descriptor_range_start + index as u32,
@ -548,8 +544,10 @@ pub(crate) fn check_descriptor_write<'a>(
} }
// VUID-VkDescriptorImageInfo-imageView-01976 // VUID-VkDescriptorImageInfo-imageView-01976
if image_view.subresource_range().aspects.depth if image_view
&& image_view.subresource_range().aspects.stencil .subresource_range()
.aspects
.contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
{ {
return Err(DescriptorSetUpdateError::ImageViewDepthAndStencil { return Err(DescriptorSetUpdateError::ImageViewDepthAndStencil {
binding: write.binding(), binding: write.binding(),
@ -571,7 +569,7 @@ pub(crate) fn check_descriptor_write<'a>(
assert_eq!(device, image_view.device()); assert_eq!(device, image_view.device());
// VUID-VkWriteDescriptorSet-descriptorType-00337 // VUID-VkWriteDescriptorSet-descriptorType-00337
if !image_view.usage().sampled { if !image_view.usage().intersects(ImageUsage::SAMPLED) {
return Err(DescriptorSetUpdateError::MissingUsage { return Err(DescriptorSetUpdateError::MissingUsage {
binding: write.binding(), binding: write.binding(),
index: descriptor_range_start + index as u32, index: descriptor_range_start + index as u32,
@ -593,8 +591,10 @@ pub(crate) fn check_descriptor_write<'a>(
} }
// VUID-VkDescriptorImageInfo-imageView-01976 // VUID-VkDescriptorImageInfo-imageView-01976
if image_view.subresource_range().aspects.depth if image_view
&& image_view.subresource_range().aspects.stencil .subresource_range()
.aspects
.contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
{ {
return Err(DescriptorSetUpdateError::ImageViewDepthAndStencil { return Err(DescriptorSetUpdateError::ImageViewDepthAndStencil {
binding: write.binding(), binding: write.binding(),
@ -618,7 +618,7 @@ pub(crate) fn check_descriptor_write<'a>(
assert_eq!(device, image_view.device()); assert_eq!(device, image_view.device());
// VUID-VkWriteDescriptorSet-descriptorType-00339 // VUID-VkWriteDescriptorSet-descriptorType-00339
if !image_view.usage().storage { if !image_view.usage().intersects(ImageUsage::STORAGE) {
return Err(DescriptorSetUpdateError::MissingUsage { return Err(DescriptorSetUpdateError::MissingUsage {
binding: write.binding(), binding: write.binding(),
index: descriptor_range_start + index as u32, index: descriptor_range_start + index as u32,
@ -640,8 +640,10 @@ pub(crate) fn check_descriptor_write<'a>(
} }
// VUID-VkDescriptorImageInfo-imageView-01976 // VUID-VkDescriptorImageInfo-imageView-01976
if image_view.subresource_range().aspects.depth if image_view
&& image_view.subresource_range().aspects.stencil .subresource_range()
.aspects
.contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
{ {
return Err(DescriptorSetUpdateError::ImageViewDepthAndStencil { return Err(DescriptorSetUpdateError::ImageViewDepthAndStencil {
binding: write.binding(), binding: write.binding(),
@ -673,7 +675,7 @@ pub(crate) fn check_descriptor_write<'a>(
assert_eq!(device, image_view.device()); assert_eq!(device, image_view.device());
// VUID-VkWriteDescriptorSet-descriptorType-00338 // VUID-VkWriteDescriptorSet-descriptorType-00338
if !image_view.usage().input_attachment { if !image_view.usage().intersects(ImageUsage::INPUT_ATTACHMENT) {
return Err(DescriptorSetUpdateError::MissingUsage { return Err(DescriptorSetUpdateError::MissingUsage {
binding: write.binding(), binding: write.binding(),
index: descriptor_range_start + index as u32, index: descriptor_range_start + index as u32,
@ -695,8 +697,10 @@ pub(crate) fn check_descriptor_write<'a>(
} }
// VUID-VkDescriptorImageInfo-imageView-01976 // VUID-VkDescriptorImageInfo-imageView-01976
if image_view.subresource_range().aspects.depth if image_view
&& image_view.subresource_range().aspects.stencil .subresource_range()
.aspects
.contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
{ {
return Err(DescriptorSetUpdateError::ImageViewDepthAndStencil { return Err(DescriptorSetUpdateError::ImageViewDepthAndStencil {
binding: write.binding(), binding: write.binding(),
@ -752,7 +756,7 @@ pub(crate) fn check_descriptor_write<'a>(
assert_eq!(device, sampler.device()); assert_eq!(device, sampler.device());
// VUID-VkWriteDescriptorSet-descriptorType-00337 // VUID-VkWriteDescriptorSet-descriptorType-00337
if !image_view.usage().sampled { if !image_view.usage().intersects(ImageUsage::SAMPLED) {
return Err(DescriptorSetUpdateError::MissingUsage { return Err(DescriptorSetUpdateError::MissingUsage {
binding: write.binding(), binding: write.binding(),
index: descriptor_range_start + index as u32, index: descriptor_range_start + index as u32,
@ -774,8 +778,10 @@ pub(crate) fn check_descriptor_write<'a>(
} }
// VUID-VkDescriptorImageInfo-imageView-01976 // VUID-VkDescriptorImageInfo-imageView-01976
if image_view.subresource_range().aspects.depth if image_view
&& image_view.subresource_range().aspects.stencil .subresource_range()
.aspects
.contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
{ {
return Err(DescriptorSetUpdateError::ImageViewDepthAndStencil { return Err(DescriptorSetUpdateError::ImageViewDepthAndStencil {
binding: write.binding(), binding: write.binding(),

View File

@ -14,15 +14,15 @@ use crate::{
device::{properties::Properties, DeviceExtensions, Features, FeaturesFfi, PropertiesFfi}, device::{properties::Properties, DeviceExtensions, Features, FeaturesFfi, PropertiesFfi},
format::{Format, FormatProperties}, format::{Format, FormatProperties},
image::{ image::{
ImageFormatInfo, ImageFormatProperties, ImageUsage, SparseImageFormatInfo, ImageAspects, ImageFormatInfo, ImageFormatProperties, ImageUsage, SparseImageFormatInfo,
SparseImageFormatProperties, SparseImageFormatProperties,
}, },
instance::Instance, instance::Instance,
macros::{vulkan_bitflags, vulkan_enum}, macros::{vulkan_bitflags, vulkan_enum},
memory::MemoryProperties, memory::MemoryProperties,
swapchain::{ swapchain::{
ColorSpace, FullScreenExclusive, PresentMode, SupportedSurfaceTransforms, Surface, ColorSpace, FullScreenExclusive, PresentMode, Surface, SurfaceApi, SurfaceCapabilities,
SurfaceApi, SurfaceCapabilities, SurfaceInfo, SurfaceInfo, SurfaceTransforms,
}, },
sync::{ sync::{
ExternalFenceInfo, ExternalFenceProperties, ExternalSemaphoreInfo, ExternalFenceInfo, ExternalFenceProperties, ExternalSemaphoreInfo,
@ -442,7 +442,7 @@ impl PhysicalDevice {
) -> Result<(), PhysicalDeviceError> { ) -> Result<(), PhysicalDeviceError> {
if !self.instance.enabled_extensions().ext_directfb_surface { if !self.instance.enabled_extensions().ext_directfb_surface {
return Err(PhysicalDeviceError::RequirementNotMet { return Err(PhysicalDeviceError::RequirementNotMet {
required_for: "`directfb_presentation_support`", required_for: "`PhysicalDevice::directfb_presentation_support`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
instance_extensions: &["ext_directfb_surface"], instance_extensions: &["ext_directfb_surface"],
..Default::default() ..Default::default()
@ -510,7 +510,7 @@ impl PhysicalDevice {
.khr_external_memory_capabilities) .khr_external_memory_capabilities)
{ {
return Err(PhysicalDeviceError::RequirementNotMet { return Err(PhysicalDeviceError::RequirementNotMet {
required_for: "`external_buffer_properties`", required_for: "`PhysicalDevice::external_buffer_properties`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
api_version: Some(Version::V1_1), api_version: Some(Version::V1_1),
instance_extensions: &["khr_external_memory_capabilities"], instance_extensions: &["khr_external_memory_capabilities"],
@ -623,7 +623,7 @@ impl PhysicalDevice {
.khr_external_fence_capabilities) .khr_external_fence_capabilities)
{ {
return Err(PhysicalDeviceError::RequirementNotMet { return Err(PhysicalDeviceError::RequirementNotMet {
required_for: "`external_fence_properties`", required_for: "`PhysicalDevice::external_fence_properties`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
api_version: Some(Version::V1_1), api_version: Some(Version::V1_1),
instance_extensions: &["khr_external_fence_capabilities"], instance_extensions: &["khr_external_fence_capabilities"],
@ -731,7 +731,7 @@ impl PhysicalDevice {
.khr_external_semaphore_capabilities) .khr_external_semaphore_capabilities)
{ {
return Err(PhysicalDeviceError::RequirementNotMet { return Err(PhysicalDeviceError::RequirementNotMet {
required_for: "`external_semaphore_properties`", required_for: "`PhysicalDevice::external_semaphore_properties`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
api_version: Some(Version::V1_1), api_version: Some(Version::V1_1),
instance_extensions: &["khr_external_semaphore_capabilities"], instance_extensions: &["khr_external_semaphore_capabilities"],
@ -941,13 +941,14 @@ impl PhysicalDevice {
let format = format.unwrap(); let format = format.unwrap();
let aspects = format.aspects(); let aspects = format.aspects();
let has_separate_stencil_usage = let has_separate_stencil_usage = if stencil_usage.is_empty()
if stencil_usage.is_empty() || !(aspects.depth && aspects.stencil) { || !aspects.contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
stencil_usage = usage; {
false stencil_usage = usage;
} else { false
stencil_usage == usage } else {
}; stencil_usage == usage
};
// VUID-VkPhysicalDeviceImageFormatInfo2-format-parameter // VUID-VkPhysicalDeviceImageFormatInfo2-format-parameter
format.validate_physical_device(self)?; format.validate_physical_device(self)?;
@ -969,7 +970,8 @@ impl PhysicalDevice {
|| self.supported_extensions().ext_separate_stencil_usage) || self.supported_extensions().ext_separate_stencil_usage)
{ {
return Err(PhysicalDeviceError::RequirementNotMet { return Err(PhysicalDeviceError::RequirementNotMet {
required_for: "`image_format_info.stencil_usage` is `Some` and `image_format_info.format` has both a depth and a stencil aspect", required_for: "`image_format_info.stencil_usage` is `Some` and \
`image_format_info.format` has both a depth and a stencil aspect",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
api_version: Some(Version::V1_2), api_version: Some(Version::V1_2),
device_extensions: &["ext_separate_stencil_usage"], device_extensions: &["ext_separate_stencil_usage"],
@ -1040,7 +1042,9 @@ impl PhysicalDevice {
let aspects = format.unwrap().aspects(); let aspects = format.unwrap().aspects();
if stencil_usage.is_empty() || !(aspects.depth && aspects.stencil) { if stencil_usage.is_empty()
|| !aspects.contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
{
*stencil_usage = *usage; *stencil_usage = *usage;
} }
} }
@ -1213,7 +1217,7 @@ impl PhysicalDevice {
) -> Result<(), PhysicalDeviceError> { ) -> Result<(), PhysicalDeviceError> {
if !self.instance.enabled_extensions().qnx_screen_surface { if !self.instance.enabled_extensions().qnx_screen_surface {
return Err(PhysicalDeviceError::RequirementNotMet { return Err(PhysicalDeviceError::RequirementNotMet {
required_for: "`qnx_screen_presentation_support`", required_for: "`PhysicalDevice::qnx_screen_presentation_support`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
instance_extensions: &["qnx_screen_surface"], instance_extensions: &["qnx_screen_surface"],
..Default::default() ..Default::default()
@ -1486,7 +1490,7 @@ impl PhysicalDevice {
|| self.instance.enabled_extensions().khr_surface) || self.instance.enabled_extensions().khr_surface)
{ {
return Err(PhysicalDeviceError::RequirementNotMet { return Err(PhysicalDeviceError::RequirementNotMet {
required_for: "`surface_capabilities`", required_for: "`PhysicalDevice::surface_capabilities`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
instance_extensions: &["khr_get_surface_capabilities2", "khr_surface"], instance_extensions: &["khr_get_surface_capabilities2", "khr_surface"],
..Default::default() ..Default::default()
@ -1655,10 +1659,10 @@ impl PhysicalDevice {
.supported_transforms .supported_transforms
.into(), .into(),
current_transform: SupportedSurfaceTransforms::from( current_transform: SurfaceTransforms::from(
capabilities_vk.surface_capabilities.current_transform, capabilities_vk.surface_capabilities.current_transform,
) )
.iter() .into_iter()
.next() .next()
.unwrap(), // TODO: .unwrap(), // TODO:
supported_composite_alpha: capabilities_vk supported_composite_alpha: capabilities_vk
@ -1668,7 +1672,7 @@ impl PhysicalDevice {
supported_usage_flags: { supported_usage_flags: {
let usage = let usage =
ImageUsage::from(capabilities_vk.surface_capabilities.supported_usage_flags); ImageUsage::from(capabilities_vk.surface_capabilities.supported_usage_flags);
debug_assert!(usage.color_attachment); // specs say that this must be true debug_assert!(usage.intersects(ImageUsage::COLOR_ATTACHMENT)); // specs say that this must be true
usage usage
}, },
@ -1711,7 +1715,7 @@ impl PhysicalDevice {
|| self.instance.enabled_extensions().khr_surface) || self.instance.enabled_extensions().khr_surface)
{ {
return Err(PhysicalDeviceError::RequirementNotMet { return Err(PhysicalDeviceError::RequirementNotMet {
required_for: "`surface_formats`", required_for: "`PhysicalDevice::surface_formats`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
instance_extensions: &["khr_get_surface_capabilities2", "khr_surface"], instance_extensions: &["khr_get_surface_capabilities2", "khr_surface"],
..Default::default() ..Default::default()
@ -1928,7 +1932,7 @@ impl PhysicalDevice {
fn validate_surface_present_modes(&self, surface: &Surface) -> Result<(), PhysicalDeviceError> { fn validate_surface_present_modes(&self, surface: &Surface) -> Result<(), PhysicalDeviceError> {
if !self.instance.enabled_extensions().khr_surface { if !self.instance.enabled_extensions().khr_surface {
return Err(PhysicalDeviceError::RequirementNotMet { return Err(PhysicalDeviceError::RequirementNotMet {
required_for: "`surface_present_modes`", required_for: "`PhysicalDevice::surface_present_modes`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
instance_extensions: &["khr_surface"], instance_extensions: &["khr_surface"],
..Default::default() ..Default::default()
@ -2022,7 +2026,7 @@ impl PhysicalDevice {
) -> Result<(), PhysicalDeviceError> { ) -> Result<(), PhysicalDeviceError> {
if !self.instance.enabled_extensions().khr_surface { if !self.instance.enabled_extensions().khr_surface {
return Err(PhysicalDeviceError::RequirementNotMet { return Err(PhysicalDeviceError::RequirementNotMet {
required_for: "`surface_support`", required_for: "`PhysicalDevice::surface_support`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
instance_extensions: &["khr_surface"], instance_extensions: &["khr_surface"],
..Default::default() ..Default::default()
@ -2084,7 +2088,7 @@ impl PhysicalDevice {
fn validate_tool_properties(&self) -> Result<(), PhysicalDeviceError> { fn validate_tool_properties(&self) -> Result<(), PhysicalDeviceError> {
if !(self.api_version() >= Version::V1_3 || self.supported_extensions().ext_tooling_info) { if !(self.api_version() >= Version::V1_3 || self.supported_extensions().ext_tooling_info) {
return Err(PhysicalDeviceError::RequirementNotMet { return Err(PhysicalDeviceError::RequirementNotMet {
required_for: "`tooling_properties`", required_for: "`PhysicalDevice::tooling_properties`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
api_version: Some(Version::V1_3), api_version: Some(Version::V1_3),
device_extensions: &["ext_tooling_info"], device_extensions: &["ext_tooling_info"],
@ -2195,7 +2199,7 @@ impl PhysicalDevice {
) -> Result<(), PhysicalDeviceError> { ) -> Result<(), PhysicalDeviceError> {
if !self.instance.enabled_extensions().khr_wayland_surface { if !self.instance.enabled_extensions().khr_wayland_surface {
return Err(PhysicalDeviceError::RequirementNotMet { return Err(PhysicalDeviceError::RequirementNotMet {
required_for: "`wayland_presentation_support`", required_for: "`PhysicalDevice::wayland_presentation_support`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
instance_extensions: &["khr_wayland_surface"], instance_extensions: &["khr_wayland_surface"],
..Default::default() ..Default::default()
@ -2250,7 +2254,7 @@ impl PhysicalDevice {
) -> Result<(), PhysicalDeviceError> { ) -> Result<(), PhysicalDeviceError> {
if !self.instance.enabled_extensions().khr_win32_surface { if !self.instance.enabled_extensions().khr_win32_surface {
return Err(PhysicalDeviceError::RequirementNotMet { return Err(PhysicalDeviceError::RequirementNotMet {
required_for: "`win32_presentation_support`", required_for: "`PhysicalDevice::win32_presentation_support`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
instance_extensions: &["khr_win32_surface"], instance_extensions: &["khr_win32_surface"],
..Default::default() ..Default::default()
@ -2304,7 +2308,7 @@ impl PhysicalDevice {
) -> Result<(), PhysicalDeviceError> { ) -> Result<(), PhysicalDeviceError> {
if !self.instance.enabled_extensions().khr_xcb_surface { if !self.instance.enabled_extensions().khr_xcb_surface {
return Err(PhysicalDeviceError::RequirementNotMet { return Err(PhysicalDeviceError::RequirementNotMet {
required_for: "`xcb_presentation_support`", required_for: "`PhysicalDevice::xcb_presentation_support`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
instance_extensions: &["khr_xcb_surface"], instance_extensions: &["khr_xcb_surface"],
..Default::default() ..Default::default()
@ -2368,7 +2372,7 @@ impl PhysicalDevice {
) -> Result<(), PhysicalDeviceError> { ) -> Result<(), PhysicalDeviceError> {
if !self.instance.enabled_extensions().khr_xlib_surface { if !self.instance.enabled_extensions().khr_xlib_surface {
return Err(PhysicalDeviceError::RequirementNotMet { return Err(PhysicalDeviceError::RequirementNotMet {
required_for: "`xlib_presentation_support`", required_for: "`PhysicalDevice::xlib_presentation_support`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
instance_extensions: &["khr_xlib_surface"], instance_extensions: &["khr_xlib_surface"],
..Default::default() ..Default::default()
@ -2420,8 +2424,9 @@ unsafe impl VulkanObject for PhysicalDevice {
crate::impl_id_counter!(PhysicalDevice); crate::impl_id_counter!(PhysicalDevice);
vulkan_enum! { vulkan_enum! {
/// Type of a physical device.
#[non_exhaustive] #[non_exhaustive]
/// Type of a physical device.
PhysicalDeviceType = PhysicalDeviceType(i32); PhysicalDeviceType = PhysicalDeviceType(i32);
/// The device is an integrated GPU. /// The device is an integrated GPU.
@ -2482,8 +2487,9 @@ impl Display for ConformanceVersion {
} }
vulkan_enum! { vulkan_enum! {
/// An identifier for the driver of a physical device.
#[non_exhaustive] #[non_exhaustive]
/// An identifier for the driver of a physical device.
DriverId = DriverId(i32); DriverId = DriverId(i32);
// TODO: document // TODO: document
@ -2550,78 +2556,81 @@ pub struct ToolProperties {
} }
vulkan_bitflags! { vulkan_bitflags! {
/// The purpose of an active tool.
#[non_exhaustive] #[non_exhaustive]
/// The purpose of an active tool.
ToolPurposes = ToolPurposeFlags(u32); ToolPurposes = ToolPurposeFlags(u32);
/// The tool provides validation of API usage. /// The tool provides validation of API usage.
validation = VALIDATION, VALIDATION = VALIDATION,
/// The tool provides profiling of API usage. /// The tool provides profiling of API usage.
profiling = PROFILING, PROFILING = PROFILING,
/// The tool is capturing data about the application's API usage. /// The tool is capturing data about the application's API usage.
tracing = TRACING, TRACING = TRACING,
/// The tool provides additional API features or extensions on top of the underlying /// The tool provides additional API features or extensions on top of the underlying
/// implementation. /// implementation.
additional_features = ADDITIONAL_FEATURES, ADDITIONAL_FEATURES = ADDITIONAL_FEATURES,
/// The tool modifies the API features, limits or extensions presented to the application. /// The tool modifies the API features, limits or extensions presented to the application.
modifying_features = MODIFYING_FEATURES, MODIFYING_FEATURES = MODIFYING_FEATURES,
/// The tool reports information to the user via a /// The tool reports information to the user via a
/// [`DebugUtilsMessenger`](crate::instance::debug::DebugUtilsMessenger). /// [`DebugUtilsMessenger`](crate::instance::debug::DebugUtilsMessenger).
debug_reporting = DEBUG_REPORTING_EXT { DEBUG_REPORTING = DEBUG_REPORTING_EXT {
instance_extensions: [ext_debug_utils, ext_debug_report], instance_extensions: [ext_debug_utils, ext_debug_report],
}, },
/// The tool consumes debug markers or object debug annotation, queue labels or command buffer /// The tool consumes debug markers or object debug annotation, queue labels or command buffer
/// labels. /// labels.
debug_markers = DEBUG_MARKERS_EXT { DEBUG_MARKERS = DEBUG_MARKERS_EXT {
device_extensions: [ext_debug_marker], device_extensions: [ext_debug_marker],
instance_extensions: [ext_debug_utils], instance_extensions: [ext_debug_utils],
}, },
} }
vulkan_bitflags! { vulkan_bitflags! {
/// Specifies which subgroup operations are supported.
#[non_exhaustive] #[non_exhaustive]
/// Specifies which subgroup operations are supported.
SubgroupFeatures = SubgroupFeatureFlags(u32); SubgroupFeatures = SubgroupFeatureFlags(u32);
// TODO: document // TODO: document
basic = BASIC, BASIC = BASIC,
// TODO: document // TODO: document
vote = VOTE, VOTE = VOTE,
// TODO: document // TODO: document
arithmetic = ARITHMETIC, ARITHMETIC = ARITHMETIC,
// TODO: document // TODO: document
ballot = BALLOT, BALLOT = BALLOT,
// TODO: document // TODO: document
shuffle = SHUFFLE, SHUFFLE = SHUFFLE,
// TODO: document // TODO: document
shuffle_relative = SHUFFLE_RELATIVE, SHUFFLE_RELATIVE = SHUFFLE_RELATIVE,
// TODO: document // TODO: document
clustered = CLUSTERED, CLUSTERED = CLUSTERED,
// TODO: document // TODO: document
quad = QUAD, QUAD = QUAD,
// TODO: document // TODO: document
partitioned = PARTITIONED_NV { PARTITIONED = PARTITIONED_NV {
device_extensions: [nv_shader_subgroup_partitioned], device_extensions: [nv_shader_subgroup_partitioned],
}, },
} }
vulkan_enum! { vulkan_enum! {
/// Specifies how the device clips single point primitives.
#[non_exhaustive] #[non_exhaustive]
/// Specifies how the device clips single point primitives.
PointClippingBehavior = PointClippingBehavior(i32); PointClippingBehavior = PointClippingBehavior(i32);
/// Points are clipped if they lie outside any clip plane, both those bounding the view volume /// Points are clipped if they lie outside any clip plane, both those bounding the view volume
@ -2633,8 +2642,9 @@ vulkan_enum! {
} }
vulkan_enum! { vulkan_enum! {
/// Specifies whether, and how, shader float controls can be set independently.
#[non_exhaustive] #[non_exhaustive]
/// Specifies whether, and how, shader float controls can be set independently.
ShaderFloatControlsIndependence = ShaderFloatControlsIndependence(i32); ShaderFloatControlsIndependence = ShaderFloatControlsIndependence(i32);
// TODO: document // TODO: document

View File

@ -1126,7 +1126,7 @@ impl<'a> QueueGuard<'a> {
.ext_debug_utils .ext_debug_utils
{ {
return Err(QueueError::RequirementNotMet { return Err(QueueError::RequirementNotMet {
required_for: "`begin_debug_utils_label`", required_for: "`QueueGuard::begin_debug_utils_label`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
instance_extensions: &["ext_debug_utils"], instance_extensions: &["ext_debug_utils"],
..Default::default() ..Default::default()
@ -1183,7 +1183,7 @@ impl<'a> QueueGuard<'a> {
.ext_debug_utils .ext_debug_utils
{ {
return Err(QueueError::RequirementNotMet { return Err(QueueError::RequirementNotMet {
required_for: "`end_debug_utils_label`", required_for: "`QueueGuard::end_debug_utils_label`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
instance_extensions: &["ext_debug_utils"], instance_extensions: &["ext_debug_utils"],
..Default::default() ..Default::default()
@ -1233,7 +1233,7 @@ impl<'a> QueueGuard<'a> {
.ext_debug_utils .ext_debug_utils
{ {
return Err(QueueError::RequirementNotMet { return Err(QueueError::RequirementNotMet {
required_for: "`insert_debug_utils_label`", required_for: "`QueueGuard::insert_debug_utils_label`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
instance_extensions: &["ext_debug_utils"], instance_extensions: &["ext_debug_utils"],
..Default::default() ..Default::default()
@ -1592,7 +1592,7 @@ impl QueueFamilyProperties {
/// Returns whether the queues of this family support a particular pipeline stage. /// Returns whether the queues of this family support a particular pipeline stage.
#[inline] #[inline]
pub fn supports_stage(&self, stage: PipelineStage) -> bool { pub fn supports_stage(&self, stage: PipelineStage) -> bool {
ash::vk::QueueFlags::from(self.queue_flags).contains(stage.required_queue_flags()) self.queue_flags.contains(stage.required_queue_flags())
} }
} }
@ -1614,34 +1614,35 @@ impl From<ash::vk::QueueFamilyProperties> for QueueFamilyProperties {
} }
vulkan_bitflags! { vulkan_bitflags! {
/// Attributes of a queue or queue family.
#[non_exhaustive] #[non_exhaustive]
/// Attributes of a queue or queue family.
QueueFlags = QueueFlags(u32); QueueFlags = QueueFlags(u32);
/// Queues of this family can execute graphics operations. /// Queues of this family can execute graphics operations.
graphics = GRAPHICS, GRAPHICS = GRAPHICS,
/// Queues of this family can execute compute operations. /// Queues of this family can execute compute operations.
compute = COMPUTE, COMPUTE = COMPUTE,
/// Queues of this family can execute transfer operations. /// Queues of this family can execute transfer operations.
transfer = TRANSFER, TRANSFER = TRANSFER,
/// Queues of this family can execute sparse memory management operations. /// Queues of this family can execute sparse memory management operations.
sparse_binding = SPARSE_BINDING, SPARSE_BINDING = SPARSE_BINDING,
/// Queues of this family can be created using the `protected` flag. /// Queues of this family can be created using the `protected` flag.
protected = PROTECTED { PROTECTED = PROTECTED {
api_version: V1_1, api_version: V1_1,
}, },
/// Queues of this family can execute video decode operations. /// Queues of this family can execute video decode operations.
video_decode = VIDEO_DECODE_KHR { VIDEO_DECODE = VIDEO_DECODE_KHR {
device_extensions: [khr_video_decode_queue], device_extensions: [khr_video_decode_queue],
}, },
/// Queues of this family can execute video encode operations. /// Queues of this family can execute video encode operations.
video_encode = VIDEO_ENCODE_KHR { VIDEO_ENCODE = VIDEO_ENCODE_KHR {
device_extensions: [khr_video_encode_queue], device_extensions: [khr_video_encode_queue],
}, },
} }

View File

@ -107,8 +107,8 @@ impl Format {
note = "Use PhysicalDevice::format_properties instead" note = "Use PhysicalDevice::format_properties instead"
)] )]
#[inline] #[inline]
pub fn properties(&self, physical_device: PhysicalDevice) -> FormatProperties { pub fn properties(self, physical_device: PhysicalDevice) -> FormatProperties {
physical_device.format_properties(*self).unwrap() physical_device.format_properties(self).unwrap()
} }
/// Returns whether the format can be used with a storage image, without specifying /// Returns whether the format can be used with a storage image, without specifying
@ -118,9 +118,9 @@ impl Format {
/// [`shader_storage_image_write_without_format`](crate::device::Features::shader_storage_image_write_without_format) /// [`shader_storage_image_write_without_format`](crate::device::Features::shader_storage_image_write_without_format)
/// features are enabled on the device. /// features are enabled on the device.
#[inline] #[inline]
pub fn shader_storage_image_without_format(&self) -> bool { pub fn shader_storage_image_without_format(self) -> bool {
matches!( matches!(
*self, self,
Format::R8G8B8A8_UNORM Format::R8G8B8A8_UNORM
| Format::R8G8B8A8_SNORM | Format::R8G8B8A8_SNORM
| Format::R8G8B8A8_UINT | Format::R8G8B8A8_UINT
@ -254,7 +254,7 @@ pub enum ChromaSampling {
impl ChromaSampling { impl ChromaSampling {
#[inline] #[inline]
pub fn subsampled_extent(&self, mut extent: [u32; 3]) -> [u32; 3] { pub fn subsampled_extent(self, mut extent: [u32; 3]) -> [u32; 3] {
match self { match self {
ChromaSampling::Mode444 => (), ChromaSampling::Mode444 => (),
ChromaSampling::Mode422 => { ChromaSampling::Mode422 => {
@ -743,138 +743,139 @@ impl FormatProperties {
} }
vulkan_bitflags! { vulkan_bitflags! {
/// The features supported by a device for an image or buffer with a particular format.
#[non_exhaustive] #[non_exhaustive]
/// The features supported by a device for an image or buffer with a particular format.
FormatFeatures = FormatFeatureFlags2(u64); FormatFeatures = FormatFeatureFlags2(u64);
/* Image usage */ /* Image usage */
/// Can be used with a sampled image descriptor. /// Can be used with a sampled image descriptor.
sampled_image = SAMPLED_IMAGE, SAMPLED_IMAGE = SAMPLED_IMAGE,
/// Can be used with a storage image descriptor. /// Can be used with a storage image descriptor.
storage_image = STORAGE_IMAGE, STORAGE_IMAGE = STORAGE_IMAGE,
/// Can be used with a storage image descriptor with atomic operations in a shader. /// Can be used with a storage image descriptor with atomic operations in a shader.
storage_image_atomic = STORAGE_IMAGE_ATOMIC, STORAGE_IMAGE_ATOMIC = STORAGE_IMAGE_ATOMIC,
/// Can be used with a storage image descriptor for reading, without specifying a format on the /// Can be used with a storage image descriptor for reading, without specifying a format on the
/// image view. /// image view.
storage_read_without_format = STORAGE_READ_WITHOUT_FORMAT { STORAGE_READ_WITHOUT_FORMAT = STORAGE_READ_WITHOUT_FORMAT {
api_version: V1_3, api_version: V1_3,
device_extensions: [khr_format_feature_flags2], device_extensions: [khr_format_feature_flags2],
}, },
/// Can be used with a storage image descriptor for writing, without specifying a format on the /// Can be used with a storage image descriptor for writing, without specifying a format on the
/// image view. /// image view.
storage_write_without_format = STORAGE_WRITE_WITHOUT_FORMAT { STORAGE_WRITE_WITHOUT_FORMAT = STORAGE_WRITE_WITHOUT_FORMAT {
api_version: V1_3, api_version: V1_3,
device_extensions: [khr_format_feature_flags2], device_extensions: [khr_format_feature_flags2],
}, },
/// Can be used with a color attachment in a framebuffer, or with an input attachment /// Can be used with a color attachment in a framebuffer, or with an input attachment
/// descriptor. /// descriptor.
color_attachment = COLOR_ATTACHMENT, COLOR_ATTACHMENT = COLOR_ATTACHMENT,
/// Can be used with a color attachment in a framebuffer with blending, or with an input /// Can be used with a color attachment in a framebuffer with blending, or with an input
/// attachment descriptor. /// attachment descriptor.
color_attachment_blend = COLOR_ATTACHMENT_BLEND, COLOR_ATTACHMENT_BLEND = COLOR_ATTACHMENT_BLEND,
/// Can be used with a depth/stencil attachment in a framebuffer, or with an input attachment /// Can be used with a depth/stencil attachment in a framebuffer, or with an input attachment
/// descriptor. /// descriptor.
depth_stencil_attachment = DEPTH_STENCIL_ATTACHMENT, DEPTH_STENCIL_ATTACHMENT = DEPTH_STENCIL_ATTACHMENT,
/// Can be used with a fragment density map attachment in a framebuffer. /// Can be used with a fragment density map attachment in a framebuffer.
fragment_density_map = FRAGMENT_DENSITY_MAP_EXT { FRAGMENT_DENSITY_MAP = FRAGMENT_DENSITY_MAP_EXT {
device_extensions: [ext_fragment_density_map], device_extensions: [ext_fragment_density_map],
}, },
/// Can be used with a fragment shading rate attachment in a framebuffer. /// Can be used with a fragment shading rate attachment in a framebuffer.
fragment_shading_rate_attachment = FRAGMENT_SHADING_RATE_ATTACHMENT_KHR { FRAGMENT_SHADING_RATE_ATTACHMENT = FRAGMENT_SHADING_RATE_ATTACHMENT_KHR {
device_extensions: [khr_fragment_shading_rate], device_extensions: [khr_fragment_shading_rate],
}, },
/// Can be used with the source image in a transfer (copy) operation. /// Can be used with the source image in a transfer (copy) operation.
transfer_src = TRANSFER_SRC { TRANSFER_SRC = TRANSFER_SRC {
api_version: V1_1, api_version: V1_1,
device_extensions: [khr_maintenance1], device_extensions: [khr_maintenance1],
}, },
/// Can be used with the destination image in a transfer (copy) operation. /// Can be used with the destination image in a transfer (copy) operation.
transfer_dst = TRANSFER_DST { TRANSFER_DST = TRANSFER_DST {
api_version: V1_1, api_version: V1_1,
device_extensions: [khr_maintenance1], device_extensions: [khr_maintenance1],
}, },
/// Can be used with the source image in a blit operation. /// Can be used with the source image in a blit operation.
blit_src = BLIT_SRC, BLIT_SRC = BLIT_SRC,
/// Can be used with the destination image in a blit operation. /// Can be used with the destination image in a blit operation.
blit_dst = BLIT_DST, BLIT_DST = BLIT_DST,
/* Sampling */ /* Sampling */
/// Can be used with samplers or as a blit source, using the /// Can be used with samplers or as a blit source, using the
/// [`Linear`](crate::sampler::Filter::Linear) filter. /// [`Linear`](crate::sampler::Filter::Linear) filter.
sampled_image_filter_linear = SAMPLED_IMAGE_FILTER_LINEAR, SAMPLED_IMAGE_FILTER_LINEAR = SAMPLED_IMAGE_FILTER_LINEAR,
/// Can be used with samplers or as a blit source, using the /// Can be used with samplers or as a blit source, using the
/// [`Cubic`](crate::sampler::Filter::Cubic) filter. /// [`Cubic`](crate::sampler::Filter::Cubic) filter.
sampled_image_filter_cubic = SAMPLED_IMAGE_FILTER_CUBIC_EXT { SAMPLED_IMAGE_FILTER_CUBIC = SAMPLED_IMAGE_FILTER_CUBIC_EXT {
device_extensions: [ext_filter_cubic, img_filter_cubic], device_extensions: [ext_filter_cubic, img_filter_cubic],
}, },
/// Can be used with samplers using a reduction mode of /// Can be used with samplers using a reduction mode of
/// [`Min`](crate::sampler::SamplerReductionMode::Min) or /// [`Min`](crate::sampler::SamplerReductionMode::Min) or
/// [`Max`](crate::sampler::SamplerReductionMode::Max). /// [`Max`](crate::sampler::SamplerReductionMode::Max).
sampled_image_filter_minmax = SAMPLED_IMAGE_FILTER_MINMAX { SAMPLED_IMAGE_FILTER_MINMAX = SAMPLED_IMAGE_FILTER_MINMAX {
api_version: V1_2, api_version: V1_2,
device_extensions: [ext_sampler_filter_minmax], device_extensions: [ext_sampler_filter_minmax],
}, },
/// Can be used with sampler YCbCr conversions using a chroma offset of /// Can be used with sampler YCbCr conversions using a chroma offset of
/// [`Midpoint`](crate::sampler::ycbcr::ChromaLocation::Midpoint). /// [`Midpoint`](crate::sampler::ycbcr::ChromaLocation::Midpoint).
midpoint_chroma_samples = MIDPOINT_CHROMA_SAMPLES { MIDPOINT_CHROMA_SAMPLES = MIDPOINT_CHROMA_SAMPLES {
api_version: V1_1, api_version: V1_1,
device_extensions: [khr_sampler_ycbcr_conversion], device_extensions: [khr_sampler_ycbcr_conversion],
}, },
/// Can be used with sampler YCbCr conversions using a chroma offset of /// Can be used with sampler YCbCr conversions using a chroma offset of
/// [`CositedEven`](crate::sampler::ycbcr::ChromaLocation::CositedEven). /// [`CositedEven`](crate::sampler::ycbcr::ChromaLocation::CositedEven).
cosited_chroma_samples = COSITED_CHROMA_SAMPLES { COSITED_CHROMA_SAMPLES = COSITED_CHROMA_SAMPLES {
api_version: V1_1, api_version: V1_1,
device_extensions: [khr_sampler_ycbcr_conversion], device_extensions: [khr_sampler_ycbcr_conversion],
}, },
/// Can be used with sampler YCbCr conversions using the /// Can be used with sampler YCbCr conversions using the
/// [`Linear`](crate::sampler::Filter::Linear) chroma filter. /// [`Linear`](crate::sampler::Filter::Linear) chroma filter.
sampled_image_ycbcr_conversion_linear_filter = SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER { SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER = SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER {
api_version: V1_1, api_version: V1_1,
device_extensions: [khr_sampler_ycbcr_conversion], device_extensions: [khr_sampler_ycbcr_conversion],
}, },
/// Can be used with sampler YCbCr conversions whose chroma filter differs from the filters of /// Can be used with sampler YCbCr conversions whose chroma filter differs from the filters of
/// the base sampler. /// the base sampler.
sampled_image_ycbcr_conversion_separate_reconstruction_filter = SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER { SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER = SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER {
api_version: V1_1, api_version: V1_1,
device_extensions: [khr_sampler_ycbcr_conversion], device_extensions: [khr_sampler_ycbcr_conversion],
}, },
/// When used with a sampler YCbCr conversion, the implementation will always perform /// When used with a sampler YCbCr conversion, the implementation will always perform
/// explicit chroma reconstruction. /// explicit chroma reconstruction.
sampled_image_ycbcr_conversion_chroma_reconstruction_explicit = SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT { SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT = SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT {
api_version: V1_1, api_version: V1_1,
device_extensions: [khr_sampler_ycbcr_conversion], device_extensions: [khr_sampler_ycbcr_conversion],
}, },
/// Can be used with sampler YCbCr conversions with forced explicit reconstruction. /// Can be used with sampler YCbCr conversions with forced explicit reconstruction.
sampled_image_ycbcr_conversion_chroma_reconstruction_explicit_forceable = SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE { SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE = SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE {
api_version: V1_1, api_version: V1_1,
device_extensions: [khr_sampler_ycbcr_conversion], device_extensions: [khr_sampler_ycbcr_conversion],
}, },
/// Can be used with samplers using depth comparison. /// Can be used with samplers using depth comparison.
sampled_image_depth_comparison = SAMPLED_IMAGE_DEPTH_COMPARISON { SAMPLED_IMAGE_DEPTH_COMPARISON = SAMPLED_IMAGE_DEPTH_COMPARISON {
api_version: V1_3, api_version: V1_3,
device_extensions: [khr_format_feature_flags2], device_extensions: [khr_format_feature_flags2],
}, },
@ -882,29 +883,31 @@ vulkan_bitflags! {
/* Video */ /* Video */
/// Can be used with the output image of a video decode operation. /// Can be used with the output image of a video decode operation.
video_decode_output = VIDEO_DECODE_OUTPUT_KHR { VIDEO_DECODE_OUTPUT = VIDEO_DECODE_OUTPUT_KHR {
device_extensions: [khr_video_decode_queue], device_extensions: [khr_video_decode_queue],
}, },
/// Can be used with the DPB image of a video decode operation. /// Can be used with the DPB image of a video decode operation.
video_decode_dpb = VIDEO_DECODE_DPB_KHR { VIDEO_DECODE_DPB = VIDEO_DECODE_DPB_KHR {
device_extensions: [khr_video_decode_queue], device_extensions: [khr_video_decode_queue],
}, },
/// Can be used with the input image of a video encode operation. /// Can be used with the input image of a video encode operation.
video_encode_input = VIDEO_ENCODE_INPUT_KHR { VIDEO_ENCODE_INPUT = VIDEO_ENCODE_INPUT_KHR {
device_extensions: [khr_video_encode_queue], device_extensions: [khr_video_encode_queue],
}, },
/// Can be used with the DPB image of a video encode operation. /// Can be used with the DPB image of a video encode operation.
video_encode_dpb = VIDEO_ENCODE_DPB_KHR { VIDEO_ENCODE_DPB = VIDEO_ENCODE_DPB_KHR {
device_extensions: [khr_video_encode_queue], device_extensions: [khr_video_encode_queue],
}, },
/* Misc image features */ /* Misc image features */
/// For multi-planar formats, can be used with images created with the `disjoint` flag. /// For multi-planar formats, can be used with images created with the [`DISJOINT`] flag.
disjoint = DISJOINT { ///
/// [`DISJOINT`]: crate::image::ImageCreateFlags::DISJOINT
DISJOINT = DISJOINT {
api_version: V1_1, api_version: V1_1,
device_extensions: [khr_sampler_ycbcr_conversion], device_extensions: [khr_sampler_ycbcr_conversion],
}, },
@ -912,20 +915,20 @@ vulkan_bitflags! {
/* Buffer usage */ /* Buffer usage */
/// Can be used with a uniform texel buffer descriptor. /// Can be used with a uniform texel buffer descriptor.
uniform_texel_buffer = UNIFORM_TEXEL_BUFFER, UNIFORM_TEXEL_BUFFER = UNIFORM_TEXEL_BUFFER,
/// Can be used with a storage texel buffer descriptor. /// Can be used with a storage texel buffer descriptor.
storage_texel_buffer = STORAGE_TEXEL_BUFFER, STORAGE_TEXEL_BUFFER = STORAGE_TEXEL_BUFFER,
/// Can be used with a storage texel buffer descriptor with atomic operations in a shader. /// Can be used with a storage texel buffer descriptor with atomic operations in a shader.
storage_texel_buffer_atomic = STORAGE_TEXEL_BUFFER_ATOMIC, STORAGE_TEXEL_BUFFER_ATOMIC = STORAGE_TEXEL_BUFFER_ATOMIC,
/// Can be used as the format of a vertex attribute in the vertex input state of a graphics /// Can be used as the format of a vertex attribute in the vertex input state of a graphics
/// pipeline. /// pipeline.
vertex_buffer = VERTEX_BUFFER, VERTEX_BUFFER = VERTEX_BUFFER,
/// Can be used with the vertex buffer of an acceleration structure. /// Can be used with the vertex buffer of an acceleration structure.
acceleration_structure_vertex_buffer = ACCELERATION_STRUCTURE_VERTEX_BUFFER_KHR { ACCELERATION_STRUCTURE_VERTEX_BUFFER = ACCELERATION_STRUCTURE_VERTEX_BUFFER_KHR {
device_extensions: [khr_acceleration_structure], device_extensions: [khr_acceleration_structure],
}, },
} }

View File

@ -7,187 +7,90 @@
// notice may not be copied, modified, or distributed except // notice may not be copied, modified, or distributed except
// according to those terms. // according to those terms.
use crate::macros::{vulkan_bitflags, vulkan_enum}; use crate::macros::vulkan_bitflags_enum;
vulkan_bitflags_enum! {
#[non_exhaustive]
/// A set of [`ImageAspect`] values.
ImageAspects,
vulkan_enum! {
/// An individual data type within an image. /// An individual data type within an image.
/// ///
/// Most images have only the `Color` aspect, but some may have several. /// Most images have only the [`Color`] aspect, but some may have others.
#[non_exhaustive] ///
ImageAspect = ImageAspectFlags(u32); /// [`Color`]: ImageAspect::Color
ImageAspect,
// TODO: document = ImageAspectFlags(u32);
Color = COLOR,
// TODO: document /// The single aspect of images with a color [format], or the combined aspect of all planes of
Depth = DEPTH, /// images with a multi-planar format.
///
/// [format]: crate::format::Format
COLOR, Color = COLOR,
// TODO: document /// The single aspect of images with a depth [format], or one of the two aspects of images
Stencil = STENCIL, /// with a combined depth/stencil format.
///
/// [format]: crate::format::Format
DEPTH, Depth = DEPTH,
// TODO: document /// The single aspect of images with a stencil [format], or one of the two aspects of images
Metadata = METADATA, /// with a combined depth/stencil format.
///
/// [format]: crate::format::Format
STENCIL, Stencil = STENCIL,
// TODO: document /// An aspect used with sparse memory on some implementations, to hold implementation-defined
Plane0 = PLANE_0 { /// metadata of an image.
METADATA, Metadata = METADATA,
/// The first plane of an image with a multi-planar [format], holding the green color component.
///
/// [format]: crate::format::Format
PLANE_0, Plane0 = PLANE_0 {
api_version: V1_1, api_version: V1_1,
device_extensions: [khr_sampler_ycbcr_conversion], device_extensions: [khr_sampler_ycbcr_conversion],
}, },
// TODO: document /// The second plane of an image with a multi-planar [format], holding the blue color component
Plane1 = PLANE_1 { /// if the format has three planes, and a combination of blue and red if the format has two
/// planes.
///
/// [format]: crate::format::Format
PLANE_1, Plane1 = PLANE_1 {
api_version: V1_1, api_version: V1_1,
device_extensions: [khr_sampler_ycbcr_conversion], device_extensions: [khr_sampler_ycbcr_conversion],
}, },
// TODO: document /// The third plane of an image with a multi-planar [format], holding the red color component.
Plane2 = PLANE_2 { PLANE_2, Plane2 = PLANE_2 {
api_version: V1_1, api_version: V1_1,
device_extensions: [khr_sampler_ycbcr_conversion], device_extensions: [khr_sampler_ycbcr_conversion],
}, },
// TODO: document /// The first memory plane of images created through the [`ext_image_drm_format_modifier`]
MemoryPlane0 = MEMORY_PLANE_0_EXT { /// extension.
///
/// [`ext_image_drm_format_modifier`]: crate::device::DeviceExtensions::ext_image_drm_format_modifier
MEMORY_PLANE_0, MemoryPlane0 = MEMORY_PLANE_0_EXT {
device_extensions: [ext_image_drm_format_modifier], device_extensions: [ext_image_drm_format_modifier],
}, },
// TODO: document /// The second memory plane of images created through the [`ext_image_drm_format_modifier`]
MemoryPlane1 = MEMORY_PLANE_1_EXT { /// extension.
///
/// [`ext_image_drm_format_modifier`]: crate::device::DeviceExtensions::ext_image_drm_format_modifier
MEMORY_PLANE_1, MemoryPlane1 = MEMORY_PLANE_1_EXT {
device_extensions: [ext_image_drm_format_modifier], device_extensions: [ext_image_drm_format_modifier],
}, },
// TODO: document /// The third memory plane of images created through the [`ext_image_drm_format_modifier`]
MemoryPlane2 = MEMORY_PLANE_2_EXT { /// extension.
///
/// [`ext_image_drm_format_modifier`]: crate::device::DeviceExtensions::ext_image_drm_format_modifier
MEMORY_PLANE_2, MemoryPlane2 = MEMORY_PLANE_2_EXT {
device_extensions: [ext_image_drm_format_modifier], device_extensions: [ext_image_drm_format_modifier],
}, },
} }
vulkan_bitflags! {
/// A mask specifying one or more `ImageAspect`s.
#[non_exhaustive]
ImageAspects = ImageAspectFlags(u32);
// TODO: document
color = COLOR,
// TODO: document
depth = DEPTH,
// TODO: document
stencil = STENCIL,
// TODO: document
metadata = METADATA,
// TODO: document
plane0 = PLANE_0 {
api_version: V1_1,
device_extensions: [khr_sampler_ycbcr_conversion],
},
// TODO: document
plane1 = PLANE_1 {
api_version: V1_1,
device_extensions: [khr_sampler_ycbcr_conversion],
},
// TODO: document
plane2 = PLANE_2 {
api_version: V1_1,
device_extensions: [khr_sampler_ycbcr_conversion],
},
// TODO: document
memory_plane0 = MEMORY_PLANE_0_EXT {
device_extensions: [ext_image_drm_format_modifier],
},
// TODO: document
memory_plane1 = MEMORY_PLANE_1_EXT {
device_extensions: [ext_image_drm_format_modifier],
},
// TODO: document
memory_plane2 = MEMORY_PLANE_2_EXT {
device_extensions: [ext_image_drm_format_modifier],
},
}
impl ImageAspects {
#[inline]
pub fn iter(&self) -> impl Iterator<Item = ImageAspect> {
let Self {
color,
depth,
stencil,
metadata,
plane0,
plane1,
plane2,
memory_plane0,
memory_plane1,
memory_plane2,
_ne: _,
} = *self;
[
color.then_some(ImageAspect::Color),
depth.then_some(ImageAspect::Depth),
stencil.then_some(ImageAspect::Stencil),
metadata.then_some(ImageAspect::Metadata),
plane0.then_some(ImageAspect::Plane0),
plane1.then_some(ImageAspect::Plane1),
plane2.then_some(ImageAspect::Plane2),
memory_plane0.then_some(ImageAspect::MemoryPlane0),
memory_plane1.then_some(ImageAspect::MemoryPlane1),
memory_plane2.then_some(ImageAspect::MemoryPlane2),
]
.into_iter()
.flatten()
}
}
impl From<ImageAspect> for ImageAspects {
#[inline]
fn from(aspect: ImageAspect) -> Self {
let mut result = Self::empty();
match aspect {
ImageAspect::Color => result.color = true,
ImageAspect::Depth => result.depth = true,
ImageAspect::Stencil => result.stencil = true,
ImageAspect::Metadata => result.metadata = true,
ImageAspect::Plane0 => result.plane0 = true,
ImageAspect::Plane1 => result.plane1 = true,
ImageAspect::Plane2 => result.plane2 = true,
ImageAspect::MemoryPlane0 => result.memory_plane0 = true,
ImageAspect::MemoryPlane1 => result.memory_plane1 = true,
ImageAspect::MemoryPlane2 => result.memory_plane2 = true,
}
result
}
}
impl FromIterator<ImageAspect> for ImageAspects {
fn from_iter<T: IntoIterator<Item = ImageAspect>>(iter: T) -> Self {
let mut result = Self::empty();
for aspect in iter {
match aspect {
ImageAspect::Color => result.color = true,
ImageAspect::Depth => result.depth = true,
ImageAspect::Stencil => result.stencil = true,
ImageAspect::Metadata => result.metadata = true,
ImageAspect::Plane0 => result.plane0 = true,
ImageAspect::Plane1 => result.plane1 = true,
ImageAspect::Plane2 => result.plane2 = true,
ImageAspect::MemoryPlane0 => result.memory_plane0 = true,
ImageAspect::MemoryPlane1 => result.memory_plane1 = true,
ImageAspect::MemoryPlane2 => result.memory_plane2 = true,
}
}
result
}
}

View File

@ -10,8 +10,8 @@
use super::{ use super::{
sys::{Image, ImageMemory, RawImage}, sys::{Image, ImageMemory, RawImage},
traits::ImageContent, traits::ImageContent,
ImageAccess, ImageDescriptorLayouts, ImageError, ImageInner, ImageLayout, ImageUsage, ImageAccess, ImageAspects, ImageDescriptorLayouts, ImageError, ImageInner, ImageLayout,
SampleCount, ImageUsage, SampleCount,
}; };
use crate::{ use crate::{
device::{Device, DeviceOwned}, device::{Device, DeviceOwned},
@ -108,10 +108,7 @@ impl AttachmentImage {
dimensions: [u32; 2], dimensions: [u32; 2],
format: Format, format: Format,
) -> Result<Arc<AttachmentImage>, ImageError> { ) -> Result<Arc<AttachmentImage>, ImageError> {
let base_usage = ImageUsage { let base_usage = ImageUsage::INPUT_ATTACHMENT;
input_attachment: true,
..ImageUsage::empty()
};
AttachmentImage::new_impl( AttachmentImage::new_impl(
allocator, allocator,
@ -154,10 +151,7 @@ impl AttachmentImage {
samples: SampleCount, samples: SampleCount,
format: Format, format: Format,
) -> Result<Arc<AttachmentImage>, ImageError> { ) -> Result<Arc<AttachmentImage>, ImageError> {
let base_usage = ImageUsage { let base_usage = ImageUsage::INPUT_ATTACHMENT;
input_attachment: true,
..ImageUsage::empty()
};
AttachmentImage::new_impl(allocator, dimensions, 1, format, base_usage, samples) AttachmentImage::new_impl(allocator, dimensions, 1, format, base_usage, samples)
} }
@ -224,10 +218,7 @@ impl AttachmentImage {
dimensions: [u32; 2], dimensions: [u32; 2],
format: Format, format: Format,
) -> Result<Arc<AttachmentImage>, ImageError> { ) -> Result<Arc<AttachmentImage>, ImageError> {
let base_usage = ImageUsage { let base_usage = ImageUsage::SAMPLED;
sampled: true,
..ImageUsage::empty()
};
AttachmentImage::new_impl( AttachmentImage::new_impl(
allocator, allocator,
@ -248,11 +239,7 @@ impl AttachmentImage {
dimensions: [u32; 2], dimensions: [u32; 2],
format: Format, format: Format,
) -> Result<Arc<AttachmentImage>, ImageError> { ) -> Result<Arc<AttachmentImage>, ImageError> {
let base_usage = ImageUsage { let base_usage = ImageUsage::SAMPLED | ImageUsage::INPUT_ATTACHMENT;
sampled: true,
input_attachment: true,
..ImageUsage::empty()
};
AttachmentImage::new_impl( AttachmentImage::new_impl(
allocator, allocator,
@ -277,10 +264,7 @@ impl AttachmentImage {
samples: SampleCount, samples: SampleCount,
format: Format, format: Format,
) -> Result<Arc<AttachmentImage>, ImageError> { ) -> Result<Arc<AttachmentImage>, ImageError> {
let base_usage = ImageUsage { let base_usage = ImageUsage::SAMPLED;
sampled: true,
..ImageUsage::empty()
};
AttachmentImage::new_impl(allocator, dimensions, 1, format, base_usage, samples) AttachmentImage::new_impl(allocator, dimensions, 1, format, base_usage, samples)
} }
@ -296,11 +280,7 @@ impl AttachmentImage {
samples: SampleCount, samples: SampleCount,
format: Format, format: Format,
) -> Result<Arc<AttachmentImage>, ImageError> { ) -> Result<Arc<AttachmentImage>, ImageError> {
let base_usage = ImageUsage { let base_usage = ImageUsage::SAMPLED | ImageUsage::INPUT_ATTACHMENT;
sampled: true,
input_attachment: true,
..ImageUsage::empty()
};
AttachmentImage::new_impl(allocator, dimensions, 1, format, base_usage, samples) AttachmentImage::new_impl(allocator, dimensions, 1, format, base_usage, samples)
} }
@ -317,10 +297,7 @@ impl AttachmentImage {
dimensions: [u32; 2], dimensions: [u32; 2],
format: Format, format: Format,
) -> Result<Arc<AttachmentImage>, ImageError> { ) -> Result<Arc<AttachmentImage>, ImageError> {
let base_usage = ImageUsage { let base_usage = ImageUsage::TRANSIENT_ATTACHMENT;
transient_attachment: true,
..ImageUsage::empty()
};
AttachmentImage::new_impl( AttachmentImage::new_impl(
allocator, allocator,
@ -341,11 +318,7 @@ impl AttachmentImage {
dimensions: [u32; 2], dimensions: [u32; 2],
format: Format, format: Format,
) -> Result<Arc<AttachmentImage>, ImageError> { ) -> Result<Arc<AttachmentImage>, ImageError> {
let base_usage = ImageUsage { let base_usage = ImageUsage::TRANSIENT_ATTACHMENT | ImageUsage::INPUT_ATTACHMENT;
transient_attachment: true,
input_attachment: true,
..ImageUsage::empty()
};
AttachmentImage::new_impl( AttachmentImage::new_impl(
allocator, allocator,
@ -370,10 +343,7 @@ impl AttachmentImage {
samples: SampleCount, samples: SampleCount,
format: Format, format: Format,
) -> Result<Arc<AttachmentImage>, ImageError> { ) -> Result<Arc<AttachmentImage>, ImageError> {
let base_usage = ImageUsage { let base_usage = ImageUsage::TRANSIENT_ATTACHMENT;
transient_attachment: true,
..ImageUsage::empty()
};
AttachmentImage::new_impl(allocator, dimensions, 1, format, base_usage, samples) AttachmentImage::new_impl(allocator, dimensions, 1, format, base_usage, samples)
} }
@ -389,11 +359,7 @@ impl AttachmentImage {
samples: SampleCount, samples: SampleCount,
format: Format, format: Format,
) -> Result<Arc<AttachmentImage>, ImageError> { ) -> Result<Arc<AttachmentImage>, ImageError> {
let base_usage = ImageUsage { let base_usage = ImageUsage::TRANSIENT_ATTACHMENT | ImageUsage::INPUT_ATTACHMENT;
transient_attachment: true,
input_attachment: true,
..ImageUsage::empty()
};
AttachmentImage::new_impl(allocator, dimensions, 1, format, base_usage, samples) AttachmentImage::new_impl(allocator, dimensions, 1, format, base_usage, samples)
} }
@ -404,7 +370,7 @@ impl AttachmentImage {
dimensions: [u32; 2], dimensions: [u32; 2],
array_layers: u32, array_layers: u32,
format: Format, format: Format,
base_usage: ImageUsage, mut usage: ImageUsage,
samples: SampleCount, samples: SampleCount,
) -> Result<Arc<AttachmentImage>, ImageError> { ) -> Result<Arc<AttachmentImage>, ImageError> {
let physical_device = allocator.device().physical_device(); let physical_device = allocator.device().physical_device();
@ -421,7 +387,15 @@ impl AttachmentImage {
} }
let aspects = format.aspects(); let aspects = format.aspects();
let is_depth = aspects.depth || aspects.stencil; let is_depth_stencil = aspects.intersects(ImageAspects::DEPTH | ImageAspects::STENCIL);
if is_depth_stencil {
usage -= ImageUsage::COLOR_ATTACHMENT;
usage |= ImageUsage::DEPTH_STENCIL_ATTACHMENT;
} else {
usage |= ImageUsage::COLOR_ATTACHMENT;
usage -= ImageUsage::DEPTH_STENCIL_ATTACHMENT;
}
if format.compression().is_some() { if format.compression().is_some() {
panic!() // TODO: message? panic!() // TODO: message?
@ -437,11 +411,7 @@ impl AttachmentImage {
}, },
format: Some(format), format: Some(format),
samples, samples,
usage: ImageUsage { usage,
color_attachment: !is_depth,
depth_stencil_attachment: is_depth,
..base_usage
},
..Default::default() ..Default::default()
}, },
)?; )?;
@ -467,7 +437,7 @@ impl AttachmentImage {
Ok(Arc::new(AttachmentImage { Ok(Arc::new(AttachmentImage {
inner, inner,
attachment_layout: if is_depth { attachment_layout: if is_depth_stencil {
ImageLayout::DepthStencilAttachmentOptimal ImageLayout::DepthStencilAttachmentOptimal
} else { } else {
ImageLayout::ColorAttachmentOptimal ImageLayout::ColorAttachmentOptimal
@ -484,7 +454,7 @@ impl AttachmentImage {
dimensions: [u32; 2], dimensions: [u32; 2],
array_layers: u32, array_layers: u32,
format: Format, format: Format,
base_usage: ImageUsage, mut usage: ImageUsage,
samples: SampleCount, samples: SampleCount,
) -> Result<Arc<AttachmentImage>, ImageError> { ) -> Result<Arc<AttachmentImage>, ImageError> {
let physical_device = allocator.device().physical_device(); let physical_device = allocator.device().physical_device();
@ -501,21 +471,21 @@ impl AttachmentImage {
} }
let aspects = format.aspects(); let aspects = format.aspects();
let is_depth = aspects.depth || aspects.stencil; let is_depth_stencil = aspects.intersects(ImageAspects::DEPTH | ImageAspects::STENCIL);
let usage = ImageUsage {
color_attachment: !is_depth, if is_depth_stencil {
depth_stencil_attachment: is_depth, usage -= ImageUsage::COLOR_ATTACHMENT;
..base_usage usage |= ImageUsage::DEPTH_STENCIL_ATTACHMENT;
}; } else {
usage |= ImageUsage::COLOR_ATTACHMENT;
usage -= ImageUsage::DEPTH_STENCIL_ATTACHMENT;
}
let external_memory_properties = allocator let external_memory_properties = allocator
.device() .device()
.physical_device() .physical_device()
.image_format_properties(ImageFormatInfo { .image_format_properties(ImageFormatInfo {
flags: ImageCreateFlags { flags: ImageCreateFlags::MUTABLE_FORMAT,
mutable_format: true,
..ImageCreateFlags::empty()
},
format: Some(format), format: Some(format),
usage, usage,
external_memory_handle_type: Some(ExternalMemoryHandleType::OpaqueFd), external_memory_handle_type: Some(ExternalMemoryHandleType::OpaqueFd),
@ -530,17 +500,11 @@ impl AttachmentImage {
// VUID-VkMemoryAllocateInfo-pNext-00639 // VUID-VkMemoryAllocateInfo-pNext-00639
// Guaranteed because we always create a dedicated allocation // Guaranteed because we always create a dedicated allocation
let external_memory_handle_types = ExternalMemoryHandleTypes { let external_memory_handle_types = ExternalMemoryHandleTypes::OPAQUE_FD;
opaque_fd: true,
..ExternalMemoryHandleTypes::empty()
};
let raw_image = RawImage::new( let raw_image = RawImage::new(
allocator.device().clone(), allocator.device().clone(),
ImageCreateInfo { ImageCreateInfo {
flags: ImageCreateFlags { flags: ImageCreateFlags::MUTABLE_FORMAT,
mutable_format: true,
..ImageCreateFlags::empty()
},
dimensions: ImageDimensions::Dim2d { dimensions: ImageDimensions::Dim2d {
width: dimensions[0], width: dimensions[0],
height: dimensions[1], height: dimensions[1],
@ -577,7 +541,7 @@ impl AttachmentImage {
Ok(Arc::new(AttachmentImage { Ok(Arc::new(AttachmentImage {
inner, inner,
attachment_layout: if is_depth { attachment_layout: if is_depth_stencil {
ImageLayout::DepthStencilAttachmentOptimal ImageLayout::DepthStencilAttachmentOptimal
} else { } else {
ImageLayout::ColorAttachmentOptimal ImageLayout::ColorAttachmentOptimal

View File

@ -115,7 +115,7 @@ impl ImmutableImage {
) -> Result<(Arc<ImmutableImage>, Arc<ImmutableImageInitialization>), ImmutableImageCreationError> ) -> Result<(Arc<ImmutableImage>, Arc<ImmutableImageInitialization>), ImmutableImageCreationError>
{ {
let queue_family_indices: SmallVec<[_; 4]> = queue_family_indices.into_iter().collect(); let queue_family_indices: SmallVec<[_; 4]> = queue_family_indices.into_iter().collect();
assert!(!flags.disjoint); // TODO: adjust the code below to make this safe assert!(!flags.intersects(ImageCreateFlags::DISJOINT)); // TODO: adjust the code below to make this safe
let raw_image = RawImage::new( let raw_image = RawImage::new(
allocator.device().clone(), allocator.device().clone(),
@ -188,15 +188,8 @@ impl ImmutableImage {
I::IntoIter: ExactSizeIterator, I::IntoIter: ExactSizeIterator,
A: CommandBufferAllocator, A: CommandBufferAllocator,
{ {
let source = CpuAccessibleBuffer::from_iter( let source =
allocator, CpuAccessibleBuffer::from_iter(allocator, BufferUsage::TRANSFER_SRC, false, iter)?;
BufferUsage {
transfer_src: true,
..BufferUsage::empty()
},
false,
iter,
)?;
ImmutableImage::from_buffer( ImmutableImage::from_buffer(
allocator, allocator,
@ -246,12 +239,13 @@ impl ImmutableImage {
} }
let need_to_generate_mipmaps = has_mipmaps(mip_levels); let need_to_generate_mipmaps = has_mipmaps(mip_levels);
let usage = ImageUsage { let usage = ImageUsage::TRANSFER_DST
transfer_dst: true, | ImageUsage::SAMPLED
transfer_src: need_to_generate_mipmaps, | if need_to_generate_mipmaps {
sampled: true, ImageUsage::TRANSFER_SRC
..ImageUsage::empty() } else {
}; ImageUsage::empty()
};
let flags = ImageCreateFlags::empty(); let flags = ImageCreateFlags::empty();
let layout = ImageLayout::ShaderReadOnlyOptimal; let layout = ImageLayout::ShaderReadOnlyOptimal;

View File

@ -10,6 +10,8 @@
use crate::{descriptor_set::layout::DescriptorType, macros::vulkan_enum}; use crate::{descriptor_set::layout::DescriptorType, macros::vulkan_enum};
vulkan_enum! { vulkan_enum! {
#[non_exhaustive]
/// In-memory layout of the pixel data of an image. /// In-memory layout of the pixel data of an image.
/// ///
/// The pixel data of a Vulkan image is arranged in a particular way, which is called its /// The pixel data of a Vulkan image is arranged in a particular way, which is called its
@ -34,7 +36,6 @@ vulkan_enum! {
/// user to specify which one. Vulkano helps with this by providing sensible defaults, /// user to specify which one. Vulkano helps with this by providing sensible defaults,
/// automatically tracking the layout of each image when creating a command buffer, and adding /// automatically tracking the layout of each image when creating a command buffer, and adding
/// layout transitions where needed. /// layout transitions where needed.
#[non_exhaustive]
ImageLayout = ImageLayout(i32); ImageLayout = ImageLayout(i32);
/// The layout of the data is unknown, and the image is treated as containing no valid data. /// The layout of the data is unknown, and the image is treated as containing no valid data.

View File

@ -60,7 +60,7 @@ pub use self::{
}; };
use crate::{ use crate::{
format::Format, format::Format,
macros::{vulkan_bitflags, vulkan_enum}, macros::{vulkan_bitflags, vulkan_bitflags_enum, vulkan_enum},
memory::{ExternalMemoryHandleType, ExternalMemoryProperties}, memory::{ExternalMemoryHandleType, ExternalMemoryProperties},
DeviceSize, DeviceSize,
}; };
@ -78,8 +78,9 @@ mod usage;
pub mod view; pub mod view;
vulkan_bitflags! { vulkan_bitflags! {
/// Flags that can be set when creating a new image.
#[non_exhaustive] #[non_exhaustive]
/// Flags that can be set when creating a new image.
ImageCreateFlags = ImageCreateFlags(u32); ImageCreateFlags = ImageCreateFlags(u32);
/* /*
@ -90,7 +91,7 @@ vulkan_bitflags! {
/// ///
/// [`bind_memory`]: sys::RawImage::bind_memory /// [`bind_memory`]: sys::RawImage::bind_memory
/// [`sparse_binding`]: crate::device::Features::sparse_binding /// [`sparse_binding`]: crate::device::Features::sparse_binding
sparse_binding = SPARSE_BINDING, SPARSE_BINDING = SPARSE_BINDING,
/// The image can be used without being fully resident in memory at the time of use. /// The image can be used without being fully resident in memory at the time of use.
/// ///
@ -110,7 +111,7 @@ vulkan_bitflags! {
/// [`sparse_residency4_samples`]: crate::device::Features::sparse_residency4_samples /// [`sparse_residency4_samples`]: crate::device::Features::sparse_residency4_samples
/// [`sparse_residency8_samples`]: crate::device::Features::sparse_residency8_samples /// [`sparse_residency8_samples`]: crate::device::Features::sparse_residency8_samples
/// [`sparse_residency16_samples`]: crate::device::Features::sparse_residency16_samples /// [`sparse_residency16_samples`]: crate::device::Features::sparse_residency16_samples
sparse_residency = SPARSE_RESIDENCY, SPARSE_RESIDENCY = SPARSE_RESIDENCY,
/// The buffer's memory can alias with another image or a different part of the same image. /// The buffer's memory can alias with another image or a different part of the same image.
/// ///
@ -119,7 +120,7 @@ vulkan_bitflags! {
/// The [`sparse_residency_aliased`] feature must be enabled on the device. /// The [`sparse_residency_aliased`] feature must be enabled on the device.
/// ///
/// [`sparse_residency_aliased`]: crate::device::Features::sparse_residency_aliased /// [`sparse_residency_aliased`]: crate::device::Features::sparse_residency_aliased
sparse_aliased = SPARSE_ALIASED, SPARSE_ALIASED = SPARSE_ALIASED,
*/ */
/// For non-multi-planar formats, whether an image view wrapping the image can have a /// For non-multi-planar formats, whether an image view wrapping the image can have a
@ -127,24 +128,24 @@ vulkan_bitflags! {
/// ///
/// For multi-planar formats, whether an image view wrapping the image can be created from a /// For multi-planar formats, whether an image view wrapping the image can be created from a
/// single plane of the image. /// single plane of the image.
mutable_format = MUTABLE_FORMAT, MUTABLE_FORMAT = MUTABLE_FORMAT,
/// For 2D images, whether an image view of type [`ImageViewType::Cube`] or /// For 2D images, whether an image view of type [`ImageViewType::Cube`] or
/// [`ImageViewType::CubeArray`] can be created from the image. /// [`ImageViewType::CubeArray`] can be created from the image.
/// ///
/// [`ImageViewType::Cube`]: crate::image::view::ImageViewType::Cube /// [`ImageViewType::Cube`]: crate::image::view::ImageViewType::Cube
/// [`ImageViewType::CubeArray`]: crate::image::view::ImageViewType::CubeArray /// [`ImageViewType::CubeArray`]: crate::image::view::ImageViewType::CubeArray
cube_compatible = CUBE_COMPATIBLE, CUBE_COMPATIBLE = CUBE_COMPATIBLE,
/* /*
// TODO: document // TODO: document
alias = ALIAS { ALIAS = ALIAS {
api_version: V1_1, api_version: V1_1,
device_extensions: [khr_bind_memory2], device_extensions: [khr_bind_memory2],
}, },
// TODO: document // TODO: document
split_instance_bind_regions = SPLIT_INSTANCE_BIND_REGIONS { SPLIT_INSTANCE_BIND_REGIONS = SPLIT_INSTANCE_BIND_REGIONS {
api_version: V1_1, api_version: V1_1,
device_extensions: [khr_device_group], device_extensions: [khr_device_group],
}, },
@ -160,7 +161,7 @@ vulkan_bitflags! {
/// [`ImageViewType::Dim2dArray`]: crate::image::view::ImageViewType::Dim2dArray /// [`ImageViewType::Dim2dArray`]: crate::image::view::ImageViewType::Dim2dArray
/// [portability subset]: crate::instance#portability-subset-devices-and-the-enumerate_portability-flag /// [portability subset]: crate::instance#portability-subset-devices-and-the-enumerate_portability-flag
/// [`image_view2_d_on3_d_image`]: crate::device::Features::image_view2_d_on3_d_image /// [`image_view2_d_on3_d_image`]: crate::device::Features::image_view2_d_on3_d_image
array_2d_compatible = TYPE_2D_ARRAY_COMPATIBLE { ARRAY_2D_COMPATIBLE = TYPE_2D_ARRAY_COMPATIBLE {
api_version: V1_1, api_version: V1_1,
device_extensions: [khr_maintenance1], device_extensions: [khr_maintenance1],
}, },
@ -170,89 +171,115 @@ vulkan_bitflags! {
/// compressed texel block in the image. /// compressed texel block in the image.
/// ///
/// Requires `mutable_format`. /// Requires `mutable_format`.
block_texel_view_compatible = BLOCK_TEXEL_VIEW_COMPATIBLE { BLOCK_TEXEL_VIEW_COMPATIBLE = BLOCK_TEXEL_VIEW_COMPATIBLE {
api_version: V1_1, api_version: V1_1,
device_extensions: [khr_maintenance2], device_extensions: [khr_maintenance2],
}, },
/* /*
// TODO: document // TODO: document
extended_usage = EXTENDED_USAGE { EXTENDED_USAGE = EXTENDED_USAGE {
api_version: V1_1, api_version: V1_1,
device_extensions: [khr_maintenance2], device_extensions: [khr_maintenance2],
}, },
// TODO: document // TODO: document
protected = PROTECTED { PROTECTED = PROTECTED {
api_version: V1_1, api_version: V1_1,
}, },
*/ */
/// For images with a multi-planar format, whether each plane will have its memory bound /// For images with a multi-planar format, whether each plane will have its memory bound
/// separately, rather than having a single memory binding for the whole image. /// separately, rather than having a single memory binding for the whole image.
disjoint = DISJOINT { DISJOINT = DISJOINT {
api_version: V1_1, api_version: V1_1,
device_extensions: [khr_sampler_ycbcr_conversion], device_extensions: [khr_sampler_ycbcr_conversion],
}, },
/* /*
// TODO: document // TODO: document
corner_sampled = CORNER_SAMPLED_NV { CORNER_SAMPLED = CORNER_SAMPLED_NV {
device_extensions: [nv_corner_sampled_image], device_extensions: [nv_corner_sampled_image],
}, },
// TODO: document // TODO: document
sample_locations_compatible_depth = SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_EXT { SAMPLE_LOCATIONS_COMPATIBLE_DEPTH = SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_EXT {
device_extensions: [ext_sample_locations], device_extensions: [ext_sample_locations],
}, },
// TODO: document // TODO: document
subsampled = SUBSAMPLED_EXT { SUBSAMPLED = SUBSAMPLED_EXT {
device_extensions: [ext_fragment_density_map], device_extensions: [ext_fragment_density_map],
}, },
// TODO: document // TODO: document
multisampled_render_to_single_sampled = MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_EXT { MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED = MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_EXT {
device_extensions: [ext_multisampled_render_to_single_sampled], device_extensions: [ext_multisampled_render_to_single_sampled],
}, },
// TODO: document // TODO: document
view_2d_compatible = TYPE_2D_VIEW_COMPATIBLE_EXT { TYPE_2D_VIEW_COMPATIBLE = TYPE_2D_VIEW_COMPATIBLE_EXT {
device_extensions: [ext_image_2d_view_of_3d], device_extensions: [ext_image_2d_view_of_3d],
}, },
// TODO: document // TODO: document
fragment_density_map_offset = FRAGMENT_DENSITY_MAP_OFFSET_QCOM { FRAGMENT_DENSITY_MAP_OFFSET = FRAGMENT_DENSITY_MAP_OFFSET_QCOM {
device_extensions: [qcom_fragment_density_map_offset], device_extensions: [qcom_fragment_density_map_offset],
}, },
*/ */
} }
vulkan_enum! { vulkan_bitflags_enum! {
// TODO: document
#[non_exhaustive] #[non_exhaustive]
SampleCount = SampleCountFlags(u32);
// TODO: document /// A set of [`SampleCount`] values.
Sample1 = TYPE_1, SampleCounts impl {
/// Returns the maximum sample count in `self`.
#[inline]
pub const fn max_count(self) -> SampleCount {
if self.intersects(SampleCounts::SAMPLE_64) {
SampleCount::Sample64
} else if self.intersects(SampleCounts::SAMPLE_32) {
SampleCount::Sample32
} else if self.intersects(SampleCounts::SAMPLE_16) {
SampleCount::Sample16
} else if self.intersects(SampleCounts::SAMPLE_8) {
SampleCount::Sample8
} else if self.intersects(SampleCounts::SAMPLE_4) {
SampleCount::Sample4
} else if self.intersects(SampleCounts::SAMPLE_2) {
SampleCount::Sample2
} else {
SampleCount::Sample1
}
}
},
// TODO: document /// The number of samples per texel of an image.
Sample2 = TYPE_2, SampleCount,
// TODO: document = SampleCountFlags(u32);
Sample4 = TYPE_4,
// TODO: document /// 1 sample per texel.
Sample8 = TYPE_8, SAMPLE_1, Sample1 = TYPE_1,
// TODO: document /// 2 samples per texel.
Sample16 = TYPE_16, SAMPLE_2, Sample2 = TYPE_2,
// TODO: document /// 4 samples per texel.
Sample32 = TYPE_32, SAMPLE_4, Sample4 = TYPE_4,
// TODO: document /// 8 samples per texel.
Sample64 = TYPE_64, SAMPLE_8, Sample8 = TYPE_8,
/// 16 samples per texel.
SAMPLE_16, Sample16 = TYPE_16,
/// 32 samples per texel.
SAMPLE_32, Sample32 = TYPE_32,
/// 64 samples per texel.
SAMPLE_64, Sample64 = TYPE_64,
} }
impl TryFrom<u32> for SampleCount { impl TryFrom<u32> for SampleCount {
@ -273,63 +300,6 @@ impl TryFrom<u32> for SampleCount {
} }
} }
vulkan_bitflags! {
/// Specifies a set of [`SampleCount`] values.
#[non_exhaustive]
SampleCounts = SampleCountFlags(u32);
/// 1 sample per pixel.
sample1 = TYPE_1,
/// 2 samples per pixel.
sample2 = TYPE_2,
/// 4 samples per pixel.
sample4 = TYPE_4,
/// 8 samples per pixel.
sample8 = TYPE_8,
/// 16 samples per pixel.
sample16 = TYPE_16,
/// 32 samples per pixel.
sample32 = TYPE_32,
/// 64 samples per pixel.
sample64 = TYPE_64,
}
impl SampleCounts {
/// Returns true if `self` has the `sample_count` value set.
#[inline]
pub const fn contains_count(&self, sample_count: SampleCount) -> bool {
match sample_count {
SampleCount::Sample1 => self.sample1,
SampleCount::Sample2 => self.sample2,
SampleCount::Sample4 => self.sample4,
SampleCount::Sample8 => self.sample8,
SampleCount::Sample16 => self.sample16,
SampleCount::Sample32 => self.sample32,
SampleCount::Sample64 => self.sample64,
}
}
/// Returns the maximum sample count supported by `self`.
#[inline]
pub const fn max_count(&self) -> SampleCount {
match self {
Self { sample64: true, .. } => SampleCount::Sample64,
Self { sample32: true, .. } => SampleCount::Sample32,
Self { sample16: true, .. } => SampleCount::Sample16,
Self { sample8: true, .. } => SampleCount::Sample8,
Self { sample4: true, .. } => SampleCount::Sample4,
Self { sample2: true, .. } => SampleCount::Sample2,
_ => SampleCount::Sample1,
}
}
}
/// Specifies how many mipmaps must be allocated. /// Specifies how many mipmaps must be allocated.
/// ///
/// Note that at least one mipmap must be allocated, to store the main level of the image. /// Note that at least one mipmap must be allocated, to store the main level of the image.
@ -358,8 +328,9 @@ impl From<u32> for MipmapsCount {
} }
vulkan_enum! { vulkan_enum! {
// TODO: document
#[non_exhaustive] #[non_exhaustive]
// TODO: document
ImageType = ImageType(i32); ImageType = ImageType(i32);
// TODO: document // TODO: document
@ -373,8 +344,9 @@ vulkan_enum! {
} }
vulkan_enum! { vulkan_enum! {
// TODO: document
#[non_exhaustive] #[non_exhaustive]
// TODO: document
ImageTiling = ImageTiling(i32); ImageTiling = ImageTiling(i32);
// TODO: document // TODO: document
@ -625,11 +597,8 @@ impl ImageSubresourceLayers {
aspects: { aspects: {
let aspects = format.aspects(); let aspects = format.aspects();
if aspects.plane0 { if aspects.intersects(ImageAspects::PLANE_0) {
ImageAspects { ImageAspects::PLANE_0
plane0: true,
..ImageAspects::empty()
}
} else { } else {
aspects aspects
} }
@ -678,12 +647,8 @@ impl ImageSubresourceRange {
#[inline] #[inline]
pub fn from_parameters(format: Format, mip_levels: u32, array_layers: u32) -> Self { pub fn from_parameters(format: Format, mip_levels: u32, array_layers: u32) -> Self {
Self { Self {
aspects: ImageAspects { aspects: format.aspects()
plane0: false, - (ImageAspects::PLANE_0 | ImageAspects::PLANE_1 | ImageAspects::PLANE_2),
plane1: false,
plane2: false,
..format.aspects()
},
mip_levels: 0..mip_levels, mip_levels: 0..mip_levels,
array_layers: 0..array_layers, array_layers: 0..array_layers,
} }
@ -946,19 +911,21 @@ pub struct SparseImageFormatProperties {
} }
vulkan_bitflags! { vulkan_bitflags! {
#[non_exhaustive]
/// Flags specifying information about a sparse resource. /// Flags specifying information about a sparse resource.
SparseImageFormatFlags = SparseImageFormatFlags(u32); SparseImageFormatFlags = SparseImageFormatFlags(u32);
/// The image uses a single mip tail region for all array layers, instead of one mip tail region /// The image uses a single mip tail region for all array layers, instead of one mip tail region
/// per array layer. /// per array layer.
single_miptail = SINGLE_MIPTAIL, SINGLE_MIPTAIL = SINGLE_MIPTAIL,
/// The image's mip tail region begins with the first mip level whose dimensions are not an /// The image's mip tail region begins with the first mip level whose dimensions are not an
/// integer multiple of the corresponding sparse image block dimensions. /// integer multiple of the corresponding sparse image block dimensions.
aligned_mip_size = ALIGNED_MIP_SIZE, ALIGNED_MIP_SIZE = ALIGNED_MIP_SIZE,
/// The image uses non-standard sparse image block dimensions. /// The image uses non-standard sparse image block dimensions.
nonstandard_block_size = NONSTANDARD_BLOCK_SIZE, NONSTANDARD_BLOCK_SIZE = NONSTANDARD_BLOCK_SIZE,
} }
/// Requirements for binding memory to a sparse image. /// Requirements for binding memory to a sparse image.

View File

@ -10,8 +10,8 @@
use super::{ use super::{
sys::{Image, ImageMemory, RawImage}, sys::{Image, ImageMemory, RawImage},
traits::ImageContent, traits::ImageContent,
ImageAccess, ImageCreateFlags, ImageDescriptorLayouts, ImageDimensions, ImageError, ImageInner, ImageAccess, ImageAspects, ImageCreateFlags, ImageDescriptorLayouts, ImageDimensions,
ImageLayout, ImageUsage, ImageError, ImageInner, ImageLayout, ImageUsage,
}; };
use crate::{ use crate::{
device::{Device, DeviceOwned, Queue}, device::{Device, DeviceOwned, Queue},
@ -51,22 +51,22 @@ impl StorageImage {
queue_family_indices: impl IntoIterator<Item = u32>, queue_family_indices: impl IntoIterator<Item = u32>,
) -> Result<Arc<StorageImage>, ImageError> { ) -> Result<Arc<StorageImage>, ImageError> {
let aspects = format.aspects(); let aspects = format.aspects();
let is_depth = aspects.depth || aspects.stencil; let is_depth_stencil = aspects.intersects(ImageAspects::DEPTH | ImageAspects::STENCIL);
if format.compression().is_some() { if format.compression().is_some() {
panic!() // TODO: message? panic!() // TODO: message?
} }
let usage = ImageUsage { let usage = ImageUsage::TRANSFER_SRC
transfer_src: true, | ImageUsage::TRANSFER_DST
transfer_dst: true, | ImageUsage::SAMPLED
sampled: true, | ImageUsage::STORAGE
storage: true, | ImageUsage::INPUT_ATTACHMENT
color_attachment: !is_depth, | if is_depth_stencil {
depth_stencil_attachment: is_depth, ImageUsage::DEPTH_STENCIL_ATTACHMENT
input_attachment: true, } else {
..ImageUsage::empty() ImageUsage::COLOR_ATTACHMENT
}; };
let flags = ImageCreateFlags::empty(); let flags = ImageCreateFlags::empty();
StorageImage::with_usage( StorageImage::with_usage(
@ -89,7 +89,7 @@ impl StorageImage {
queue_family_indices: impl IntoIterator<Item = u32>, queue_family_indices: impl IntoIterator<Item = u32>,
) -> Result<Arc<StorageImage>, ImageError> { ) -> Result<Arc<StorageImage>, ImageError> {
let queue_family_indices: SmallVec<[_; 4]> = queue_family_indices.into_iter().collect(); let queue_family_indices: SmallVec<[_; 4]> = queue_family_indices.into_iter().collect();
assert!(!flags.disjoint); // TODO: adjust the code below to make this safe assert!(!flags.intersects(ImageCreateFlags::DISJOINT)); // TODO: adjust the code below to make this safe
let raw_image = RawImage::new( let raw_image = RawImage::new(
allocator.device().clone(), allocator.device().clone(),
@ -141,7 +141,7 @@ impl StorageImage {
queue_family_indices: impl IntoIterator<Item = u32>, queue_family_indices: impl IntoIterator<Item = u32>,
) -> Result<Arc<StorageImage>, ImageError> { ) -> Result<Arc<StorageImage>, ImageError> {
let queue_family_indices: SmallVec<[_; 4]> = queue_family_indices.into_iter().collect(); let queue_family_indices: SmallVec<[_; 4]> = queue_family_indices.into_iter().collect();
assert!(!flags.disjoint); // TODO: adjust the code below to make this safe assert!(!flags.intersects(ImageCreateFlags::DISJOINT)); // TODO: adjust the code below to make this safe
let external_memory_properties = allocator let external_memory_properties = allocator
.device() .device()
@ -163,10 +163,7 @@ impl StorageImage {
// VUID-VkMemoryAllocateInfo-pNext-00639 // VUID-VkMemoryAllocateInfo-pNext-00639
// Guaranteed because we always create a dedicated allocation // Guaranteed because we always create a dedicated allocation
let external_memory_handle_types = ExternalMemoryHandleTypes { let external_memory_handle_types = ExternalMemoryHandleTypes::OPAQUE_FD;
opaque_fd: true,
..ExternalMemoryHandleTypes::empty()
};
let raw_image = RawImage::new( let raw_image = RawImage::new(
allocator.device().clone(), allocator.device().clone(),
ImageCreateInfo { ImageCreateInfo {
@ -360,12 +357,8 @@ mod tests {
fn create_general_purpose_image_view() { fn create_general_purpose_image_view() {
let (device, queue) = gfx_dev_and_queue!(); let (device, queue) = gfx_dev_and_queue!();
let memory_allocator = StandardMemoryAllocator::new_default(device); let memory_allocator = StandardMemoryAllocator::new_default(device);
let usage = ImageUsage { let usage =
transfer_src: true, ImageUsage::TRANSFER_SRC | ImageUsage::TRANSFER_DST | ImageUsage::COLOR_ATTACHMENT;
transfer_dst: true,
color_attachment: true,
..ImageUsage::empty()
};
let img_view = StorageImage::general_purpose_image_view( let img_view = StorageImage::general_purpose_image_view(
&memory_allocator, &memory_allocator,
queue, queue,
@ -374,7 +367,7 @@ mod tests {
usage, usage,
) )
.unwrap(); .unwrap();
assert_eq!(img_view.image().usage(), &usage); assert_eq!(img_view.image().usage(), usage);
} }
#[test] #[test]
@ -382,10 +375,7 @@ mod tests {
let (device, queue) = gfx_dev_and_queue!(); let (device, queue) = gfx_dev_and_queue!();
let memory_allocator = StandardMemoryAllocator::new_default(device); let memory_allocator = StandardMemoryAllocator::new_default(device);
// Not valid for image view... // Not valid for image view...
let usage = ImageUsage { let usage = ImageUsage::TRANSFER_SRC;
transfer_src: true,
..ImageUsage::empty()
};
let img_result = StorageImage::general_purpose_image_view( let img_result = StorageImage::general_purpose_image_view(
&memory_allocator, &memory_allocator,
queue, queue,

View File

@ -29,7 +29,8 @@ use crate::{
}, },
memory::{ memory::{
allocator::{AllocationCreationError, MemoryAlloc}, allocator::{AllocationCreationError, MemoryAlloc},
DedicatedTo, ExternalMemoryHandleType, ExternalMemoryHandleTypes, MemoryRequirements, DedicatedTo, ExternalMemoryHandleType, ExternalMemoryHandleTypes, MemoryPropertyFlags,
MemoryRequirements,
}, },
range_map::RangeMap, range_map::RangeMap,
swapchain::Swapchain, swapchain::Swapchain,
@ -140,13 +141,14 @@ impl RawImage {
let format = format.unwrap(); // Can be None for "external formats" but Vulkano doesn't support that yet let format = format.unwrap(); // Can be None for "external formats" but Vulkano doesn't support that yet
let aspects = format.aspects(); let aspects = format.aspects();
let has_separate_stencil_usage = let has_separate_stencil_usage = if stencil_usage.is_empty()
if stencil_usage.is_empty() || !(aspects.depth && aspects.stencil) { || !aspects.contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
stencil_usage = usage; {
false stencil_usage = usage;
} else { false
stencil_usage == usage } else {
}; stencil_usage == usage
};
// VUID-VkImageCreateInfo-flags-parameter // VUID-VkImageCreateInfo-flags-parameter
flags.validate_device(device)?; flags.validate_device(device)?;
@ -171,7 +173,8 @@ impl RawImage {
|| device.enabled_extensions().ext_separate_stencil_usage) || device.enabled_extensions().ext_separate_stencil_usage)
{ {
return Err(ImageError::RequirementNotMet { return Err(ImageError::RequirementNotMet {
required_for: "`create_info.stencil_usage` is `Some` and `create_info.format` has both a depth and a stencil aspect", required_for: "`create_info.stencil_usage` is `Some` and `create_info.format` \
has both a depth and a stencil aspect",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
api_version: Some(Version::V1_2), api_version: Some(Version::V1_2),
device_extensions: &["ext_separate_stencil_usage"], device_extensions: &["ext_separate_stencil_usage"],
@ -197,7 +200,10 @@ impl RawImage {
)); ));
// VUID-VkImageCreateInfo-flags-01573 // VUID-VkImageCreateInfo-flags-01573
assert!(!flags.block_texel_view_compatible || flags.mutable_format); assert!(
!flags.intersects(ImageCreateFlags::BLOCK_TEXEL_VIEW_COMPATIBLE)
|| flags.intersects(ImageCreateFlags::MUTABLE_FORMAT)
);
// Get format features // Get format features
let format_features = { let format_features = {
@ -266,7 +272,7 @@ impl RawImage {
return Err(ImageError::MultisampleNot2d); return Err(ImageError::MultisampleNot2d);
} }
if flags.cube_compatible { if flags.intersects(ImageCreateFlags::CUBE_COMPATIBLE) {
return Err(ImageError::MultisampleCubeCompatible); return Err(ImageError::MultisampleCubeCompatible);
} }
@ -284,10 +290,9 @@ impl RawImage {
&& array_layers != 1 && array_layers != 1
{ {
return Err(ImageError::RequirementNotMet { return Err(ImageError::RequirementNotMet {
required_for: required_for: "this device is a portability subset device, \
"this device is a portability subset device, `create_info.samples` is not \ `create_info.samples` is not `SampleCount::Sample1` and \
`SampleCount::Sample1` and `create_info.dimensions.array_layers()` is \ `create_info.dimensions.array_layers()` is greater than `1`",
greater than `1`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["multisample_array_image"], features: &["multisample_array_image"],
..Default::default() ..Default::default()
@ -316,7 +321,8 @@ impl RawImage {
// VUID-VkImageCreateInfo-format-06413 // VUID-VkImageCreateInfo-format-06413
if array_layers > 1 && !device.enabled_features().ycbcr_image_arrays { if array_layers > 1 && !device.enabled_features().ycbcr_image_arrays {
return Err(ImageError::RequirementNotMet { return Err(ImageError::RequirementNotMet {
required_for: "`create_info.format.ycbcr_chroma_sampling()` is `Some` and `create_info.dimensions.array_layers()` is greater than `1`", required_for: "`create_info.format.ycbcr_chroma_sampling()` is `Some` and \
`create_info.dimensions.array_layers()` is greater than `1`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["ycbcr_image_arrays"], features: &["ycbcr_image_arrays"],
..Default::default() ..Default::default()
@ -346,35 +352,44 @@ impl RawImage {
let combined_usage = usage | stencil_usage; let combined_usage = usage | stencil_usage;
if combined_usage.sampled && !format_features.sampled_image { if combined_usage.intersects(ImageUsage::SAMPLED)
&& !format_features.intersects(FormatFeatures::SAMPLED_IMAGE)
{
return Err(ImageError::FormatUsageNotSupported { usage: "sampled" }); return Err(ImageError::FormatUsageNotSupported { usage: "sampled" });
} }
if combined_usage.color_attachment && !format_features.color_attachment { if combined_usage.intersects(ImageUsage::COLOR_ATTACHMENT)
&& !format_features.intersects(FormatFeatures::COLOR_ATTACHMENT)
{
return Err(ImageError::FormatUsageNotSupported { return Err(ImageError::FormatUsageNotSupported {
usage: "color_attachment", usage: "color_attachment",
}); });
} }
if combined_usage.depth_stencil_attachment && !format_features.depth_stencil_attachment { if combined_usage.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
&& !format_features.intersects(FormatFeatures::DEPTH_STENCIL_ATTACHMENT)
{
return Err(ImageError::FormatUsageNotSupported { return Err(ImageError::FormatUsageNotSupported {
usage: "depth_stencil_attachment", usage: "depth_stencil_attachment",
}); });
} }
if combined_usage.input_attachment if combined_usage.intersects(ImageUsage::INPUT_ATTACHMENT)
&& !(format_features.color_attachment || format_features.depth_stencil_attachment) && !format_features.intersects(
FormatFeatures::COLOR_ATTACHMENT | FormatFeatures::DEPTH_STENCIL_ATTACHMENT,
)
{ {
return Err(ImageError::FormatUsageNotSupported { return Err(ImageError::FormatUsageNotSupported {
usage: "input_attachment", usage: "input_attachment",
}); });
} }
if combined_usage.color_attachment if combined_usage.intersects(
|| combined_usage.depth_stencil_attachment ImageUsage::COLOR_ATTACHMENT
|| combined_usage.input_attachment | ImageUsage::DEPTH_STENCIL_ATTACHMENT
|| combined_usage.transient_attachment | ImageUsage::INPUT_ATTACHMENT
{ | ImageUsage::TRANSIENT_ATTACHMENT,
) {
// VUID-VkImageCreateInfo-usage-00964 // VUID-VkImageCreateInfo-usage-00964
// VUID-VkImageCreateInfo-usage-00965 // VUID-VkImageCreateInfo-usage-00965
// VUID-VkImageCreateInfo-Format-02536 // VUID-VkImageCreateInfo-Format-02536
@ -392,8 +407,8 @@ impl RawImage {
} }
} }
if combined_usage.storage { if combined_usage.intersects(ImageUsage::STORAGE) {
if !format_features.storage_image { if !format_features.intersects(FormatFeatures::STORAGE_IMAGE) {
return Err(ImageError::FormatUsageNotSupported { usage: "storage" }); return Err(ImageError::FormatUsageNotSupported { usage: "storage" });
} }
@ -403,7 +418,9 @@ impl RawImage {
&& samples != SampleCount::Sample1 && samples != SampleCount::Sample1
{ {
return Err(ImageError::RequirementNotMet { return Err(ImageError::RequirementNotMet {
required_for: "`create_info.usage.storage` or `create_info.stencil_usage.storage` is set and `create_info.samples` is not `SampleCount::Sample1`", required_for: "`create_info.usage` or `create_info.stencil_usage` contains \
`ImageUsage::STORAGE`, and `create_info.samples` is not \
`SampleCount::Sample1`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["shader_storage_image_multisample"], features: &["shader_storage_image_multisample"],
..Default::default() ..Default::default()
@ -414,40 +431,46 @@ impl RawImage {
// These flags only exist in later versions, ignore them otherwise // These flags only exist in later versions, ignore them otherwise
if device.api_version() >= Version::V1_1 || device.enabled_extensions().khr_maintenance1 { if device.api_version() >= Version::V1_1 || device.enabled_extensions().khr_maintenance1 {
if combined_usage.transfer_src && !format_features.transfer_src { if combined_usage.intersects(ImageUsage::TRANSFER_SRC)
&& !format_features.intersects(FormatFeatures::TRANSFER_SRC)
{
return Err(ImageError::FormatUsageNotSupported { return Err(ImageError::FormatUsageNotSupported {
usage: "transfer_src", usage: "transfer_src",
}); });
} }
if combined_usage.transfer_dst && !format_features.transfer_dst { if combined_usage.intersects(ImageUsage::TRANSFER_DST)
&& !format_features.intersects(FormatFeatures::TRANSFER_DST)
{
return Err(ImageError::FormatUsageNotSupported { return Err(ImageError::FormatUsageNotSupported {
usage: "transfer_dst", usage: "transfer_dst",
}); });
} }
} }
if usage.transient_attachment { if usage.intersects(ImageUsage::TRANSIENT_ATTACHMENT) {
// VUID-VkImageCreateInfo-usage-00966 // VUID-VkImageCreateInfo-usage-00966
assert!( assert!(usage.intersects(
usage.color_attachment || usage.depth_stencil_attachment || usage.input_attachment ImageUsage::COLOR_ATTACHMENT
); | ImageUsage::DEPTH_STENCIL_ATTACHMENT
| ImageUsage::INPUT_ATTACHMENT
));
// VUID-VkImageCreateInfo-usage-00963 // VUID-VkImageCreateInfo-usage-00963
assert!(ImageUsage { assert!((usage
transient_attachment: false, - (ImageUsage::TRANSIENT_ATTACHMENT
color_attachment: false, | ImageUsage::COLOR_ATTACHMENT
depth_stencil_attachment: false, | ImageUsage::DEPTH_STENCIL_ATTACHMENT
input_attachment: false, | ImageUsage::INPUT_ATTACHMENT))
..usage .is_empty())
}
.is_empty())
} }
if has_separate_stencil_usage { if has_separate_stencil_usage {
// VUID-VkImageCreateInfo-format-02795 // VUID-VkImageCreateInfo-format-02795
// VUID-VkImageCreateInfo-format-02796 // VUID-VkImageCreateInfo-format-02796
if usage.depth_stencil_attachment != stencil_usage.depth_stencil_attachment { if usage.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
!= stencil_usage.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
{
return Err(ImageError::StencilUsageMismatch { return Err(ImageError::StencilUsageMismatch {
usage, usage,
stencil_usage, stencil_usage,
@ -456,28 +479,28 @@ impl RawImage {
// VUID-VkImageCreateInfo-format-02797 // VUID-VkImageCreateInfo-format-02797
// VUID-VkImageCreateInfo-format-02798 // VUID-VkImageCreateInfo-format-02798
if usage.transient_attachment != stencil_usage.transient_attachment { if usage.intersects(ImageUsage::TRANSIENT_ATTACHMENT)
!= stencil_usage.intersects(ImageUsage::TRANSIENT_ATTACHMENT)
{
return Err(ImageError::StencilUsageMismatch { return Err(ImageError::StencilUsageMismatch {
usage, usage,
stencil_usage, stencil_usage,
}); });
} }
if stencil_usage.transient_attachment { if stencil_usage.intersects(ImageUsage::TRANSIENT_ATTACHMENT) {
// VUID-VkImageStencilUsageCreateInfo-stencilUsage-02539 // VUID-VkImageStencilUsageCreateInfo-stencilUsage-02539
assert!(ImageUsage { assert!((stencil_usage
transient_attachment: false, - (ImageUsage::TRANSIENT_ATTACHMENT
depth_stencil_attachment: false, | ImageUsage::DEPTH_STENCIL_ATTACHMENT
input_attachment: false, | ImageUsage::INPUT_ATTACHMENT))
..stencil_usage .is_empty())
}
.is_empty())
} }
} }
/* Check flags requirements */ /* Check flags requirements */
if flags.cube_compatible { if flags.intersects(ImageCreateFlags::CUBE_COMPATIBLE) {
// VUID-VkImageCreateInfo-flags-00949 // VUID-VkImageCreateInfo-flags-00949
if image_type != ImageType::Dim2d { if image_type != ImageType::Dim2d {
return Err(ImageError::CubeCompatibleNot2d); return Err(ImageError::CubeCompatibleNot2d);
@ -494,7 +517,7 @@ impl RawImage {
} }
} }
if flags.array_2d_compatible { if flags.intersects(ImageCreateFlags::ARRAY_2D_COMPATIBLE) {
// VUID-VkImageCreateInfo-flags-00950 // VUID-VkImageCreateInfo-flags-00950
if image_type != ImageType::Dim3d { if image_type != ImageType::Dim3d {
return Err(ImageError::Array2dCompatibleNot3d); return Err(ImageError::Array2dCompatibleNot3d);
@ -505,9 +528,8 @@ impl RawImage {
&& !device.enabled_features().image_view2_d_on3_d_image && !device.enabled_features().image_view2_d_on3_d_image
{ {
return Err(ImageError::RequirementNotMet { return Err(ImageError::RequirementNotMet {
required_for: required_for: "this device is a portability subset device, and \
"this device is a portability subset device, and the `array_2d_compatible` `create_info.flags` contains `ImageCreateFlags::ARRAY_2D_COMPATIBLE`",
flag is enabled",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["image_view2_d_on3_d_image"], features: &["image_view2_d_on3_d_image"],
..Default::default() ..Default::default()
@ -516,21 +538,21 @@ impl RawImage {
} }
} }
if flags.block_texel_view_compatible { if flags.intersects(ImageCreateFlags::BLOCK_TEXEL_VIEW_COMPATIBLE) {
// VUID-VkImageCreateInfo-flags-01572 // VUID-VkImageCreateInfo-flags-01572
if format.compression().is_none() { if format.compression().is_none() {
return Err(ImageError::BlockTexelViewCompatibleNotCompressed); return Err(ImageError::BlockTexelViewCompatibleNotCompressed);
} }
} }
if flags.disjoint { if flags.intersects(ImageCreateFlags::DISJOINT) {
// VUID-VkImageCreateInfo-format-01577 // VUID-VkImageCreateInfo-format-01577
if format.planes().len() < 2 { if format.planes().len() < 2 {
return Err(ImageError::DisjointFormatNotSupported); return Err(ImageError::DisjointFormatNotSupported);
} }
// VUID-VkImageCreateInfo-imageCreateFormatFeatures-02260 // VUID-VkImageCreateInfo-imageCreateFormatFeatures-02260
if !format_features.disjoint { if !format_features.intersects(FormatFeatures::DISJOINT) {
return Err(ImageError::DisjointFormatNotSupported); return Err(ImageError::DisjointFormatNotSupported);
} }
} }
@ -598,7 +620,7 @@ impl RawImage {
let limit = device.physical_device().properties().max_image_dimension1_d; let limit = device.physical_device().properties().max_image_dimension1_d;
extent[0] > limit extent[0] > limit
} }
ImageType::Dim2d if flags.cube_compatible => { ImageType::Dim2d if flags.intersects(ImageCreateFlags::CUBE_COMPATIBLE) => {
let limit = device let limit = device
.physical_device() .physical_device()
.properties() .properties()
@ -641,41 +663,41 @@ impl RawImage {
return false; return false;
} }
if combined_usage.color_attachment if combined_usage.intersects(ImageUsage::COLOR_ATTACHMENT)
&& !device_properties && !device_properties
.framebuffer_color_sample_counts .framebuffer_color_sample_counts
.contains_count(samples) .contains_enum(samples)
{ {
// TODO: how to handle framebuffer_integer_color_sample_counts limit, which only // TODO: how to handle framebuffer_integer_color_sample_counts limit, which only
// exists >= Vulkan 1.2 // exists >= Vulkan 1.2
return true; return true;
} }
if combined_usage.depth_stencil_attachment { if combined_usage.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT) {
if aspects.depth if aspects.intersects(ImageAspects::DEPTH)
&& !device_properties && !device_properties
.framebuffer_depth_sample_counts .framebuffer_depth_sample_counts
.contains_count(samples) .contains_enum(samples)
{ {
return true; return true;
} }
if aspects.stencil if aspects.intersects(ImageAspects::STENCIL)
&& !device_properties && !device_properties
.framebuffer_stencil_sample_counts .framebuffer_stencil_sample_counts
.contains_count(samples) .contains_enum(samples)
{ {
return true; return true;
} }
} }
if combined_usage.sampled { if combined_usage.intersects(ImageUsage::SAMPLED) {
if let Some(numeric_type) = format.type_color() { if let Some(numeric_type) = format.type_color() {
match numeric_type { match numeric_type {
NumericType::UINT | NumericType::SINT => { NumericType::UINT | NumericType::SINT => {
if !device_properties if !device_properties
.sampled_image_integer_sample_counts .sampled_image_integer_sample_counts
.contains_count(samples) .contains_enum(samples)
{ {
return true; return true;
} }
@ -689,35 +711,35 @@ impl RawImage {
| NumericType::SRGB => { | NumericType::SRGB => {
if !device_properties if !device_properties
.sampled_image_color_sample_counts .sampled_image_color_sample_counts
.contains_count(samples) .contains_enum(samples)
{ {
return true; return true;
} }
} }
} }
} else { } else {
if aspects.depth if aspects.intersects(ImageAspects::DEPTH)
&& !device_properties && !device_properties
.sampled_image_depth_sample_counts .sampled_image_depth_sample_counts
.contains_count(samples) .contains_enum(samples)
{ {
return true; return true;
} }
if aspects.stencil if aspects.intersects(ImageAspects::STENCIL)
&& device_properties && device_properties
.sampled_image_stencil_sample_counts .sampled_image_stencil_sample_counts
.contains_count(samples) .contains_enum(samples)
{ {
return true; return true;
} }
} }
} }
if combined_usage.storage if combined_usage.intersects(ImageUsage::STORAGE)
&& !device_properties && !device_properties
.storage_image_sample_counts .storage_image_sample_counts
.contains_count(samples) .contains_enum(samples)
{ {
return true; return true;
} }
@ -733,11 +755,7 @@ impl RawImage {
&& array_layers == 1 && array_layers == 1
// VUID-VkImageCreateInfo-samples-02257 already states that multisampling+linear // VUID-VkImageCreateInfo-samples-02257 already states that multisampling+linear
// is invalid so no need to check for that here. // is invalid so no need to check for that here.
&& ImageUsage { && (usage - (ImageUsage::TRANSFER_SRC | ImageUsage::TRANSFER_DST)).is_empty())
transfer_src: false,
transfer_dst: false,
..usage
}.is_empty())
} else { } else {
false false
} }
@ -756,7 +774,7 @@ impl RawImage {
if !external_memory_handle_types.is_empty() { if !external_memory_handle_types.is_empty() {
// If external memory handles are used, the properties need to be queried // If external memory handles are used, the properties need to be queried
// individually for each handle type. // individually for each handle type.
external_memory_handle_types.iter().map(Some).collect() external_memory_handle_types.into_iter().map(Some).collect()
} else { } else {
smallvec![None] smallvec![None]
}; };
@ -819,7 +837,7 @@ impl RawImage {
} }
// VUID-VkImageCreateInfo-samples-02258 // VUID-VkImageCreateInfo-samples-02258
if !sample_counts.contains_count(samples) { if !sample_counts.contains_enum(samples) {
return Err(ImageError::SampleCountNotSupported { return Err(ImageError::SampleCountNotSupported {
samples, samples,
supported: sample_counts, supported: sample_counts,
@ -856,13 +874,14 @@ impl RawImage {
let aspects = format.map_or_else(Default::default, |format| format.aspects()); let aspects = format.map_or_else(Default::default, |format| format.aspects());
let has_separate_stencil_usage = let has_separate_stencil_usage = if stencil_usage.is_empty()
if stencil_usage.is_empty() || !(aspects.depth && aspects.stencil) { || !aspects.contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
stencil_usage = usage; {
false stencil_usage = usage;
} else { false
stencil_usage == usage } else {
}; stencil_usage == usage
};
let (image_type, extent, array_layers) = match dimensions { let (image_type, extent, array_layers) = match dimensions {
ImageDimensions::Dim1d { ImageDimensions::Dim1d {
@ -984,7 +1003,9 @@ impl RawImage {
let aspects = format.map_or_else(Default::default, |format| format.aspects()); let aspects = format.map_or_else(Default::default, |format| format.aspects());
if stencil_usage.is_empty() || !(aspects.depth && aspects.stencil) { if stencil_usage.is_empty()
|| !aspects.contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
{
stencil_usage = usage; stencil_usage = usage;
} }
@ -1001,7 +1022,7 @@ impl RawImage {
} }
}; };
let memory_requirements = if flags.disjoint { let memory_requirements = if flags.intersects(ImageCreateFlags::DISJOINT) {
(0..format.unwrap().planes().len()) (0..format.unwrap().planes().len())
.map(|plane| Self::get_memory_requirements(&device, handle, Some(plane))) .map(|plane| Self::get_memory_requirements(&device, handle, Some(plane)))
.collect() .collect()
@ -1342,7 +1363,7 @@ impl RawImage {
} }
fn validate_bind_memory(&self, allocations: &[MemoryAlloc]) -> Result<(), ImageError> { fn validate_bind_memory(&self, allocations: &[MemoryAlloc]) -> Result<(), ImageError> {
if self.flags.disjoint { if self.flags.intersects(ImageCreateFlags::DISJOINT) {
if allocations.len() != self.format.unwrap().planes().len() { if allocations.len() != self.format.unwrap().planes().len() {
return Err(ImageError::AllocationsWrongNumberOfElements { return Err(ImageError::AllocationsWrongNumberOfElements {
provided: allocations.len(), provided: allocations.len(),
@ -1398,7 +1419,10 @@ impl RawImage {
} }
// VUID-VkBindImageMemoryInfo-None-01901 // VUID-VkBindImageMemoryInfo-None-01901
if memory_type.property_flags.protected { if memory_type
.property_flags
.intersects(MemoryPropertyFlags::PROTECTED)
{
return Err(ImageError::MemoryProtectedMismatch { return Err(ImageError::MemoryProtectedMismatch {
allocations_index, allocations_index,
image_protected: false, image_protected: false,
@ -1410,7 +1434,7 @@ impl RawImage {
if !memory.export_handle_types().is_empty() if !memory.export_handle_types().is_empty()
&& !memory && !memory
.export_handle_types() .export_handle_types()
.intersects(&self.external_memory_handle_types) .intersects(self.external_memory_handle_types)
{ {
return Err(ImageError::MemoryExternalHandleTypesDisjoint { return Err(ImageError::MemoryExternalHandleTypesDisjoint {
allocations_index, allocations_index,
@ -1422,7 +1446,7 @@ impl RawImage {
if let Some(handle_type) = memory.imported_handle_type() { if let Some(handle_type) = memory.imported_handle_type() {
// VUID-VkBindImageMemoryInfo-memory-02989 // VUID-VkBindImageMemoryInfo-memory-02989
if !ExternalMemoryHandleTypes::from(handle_type) if !ExternalMemoryHandleTypes::from(handle_type)
.intersects(&self.external_memory_handle_types) .intersects(self.external_memory_handle_types)
{ {
return Err(ImageError::MemoryImportedHandleTypeNotEnabled { return Err(ImageError::MemoryImportedHandleTypeNotEnabled {
allocations_index, allocations_index,
@ -1493,7 +1517,7 @@ impl RawImage {
let mut infos_vk: SmallVec<[_; 3]> = SmallVec::with_capacity(3); let mut infos_vk: SmallVec<[_; 3]> = SmallVec::with_capacity(3);
let mut plane_infos_vk: SmallVec<[_; 3]> = SmallVec::with_capacity(3); let mut plane_infos_vk: SmallVec<[_; 3]> = SmallVec::with_capacity(3);
if self.flags.disjoint { if self.flags.intersects(ImageCreateFlags::DISJOINT) {
debug_assert_eq!(allocations.len(), self.format.unwrap().planes().len()); debug_assert_eq!(allocations.len(), self.format.unwrap().planes().len());
for (plane, allocation) in allocations.iter().enumerate() { for (plane, allocation) in allocations.iter().enumerate() {
@ -1602,8 +1626,8 @@ impl RawImage {
/// Returns the features supported by the image's format. /// Returns the features supported by the image's format.
#[inline] #[inline]
pub fn format_features(&self) -> &FormatFeatures { pub fn format_features(&self) -> FormatFeatures {
&self.format_features self.format_features
} }
/// Returns the number of mipmap levels in the image. /// Returns the number of mipmap levels in the image.
@ -1632,14 +1656,14 @@ impl RawImage {
/// Returns the usage the image was created with. /// Returns the usage the image was created with.
#[inline] #[inline]
pub fn usage(&self) -> &ImageUsage { pub fn usage(&self) -> ImageUsage {
&self.usage self.usage
} }
/// Returns the stencil usage the image was created with. /// Returns the stencil usage the image was created with.
#[inline] #[inline]
pub fn stencil_usage(&self) -> &ImageUsage { pub fn stencil_usage(&self) -> ImageUsage {
&self.stencil_usage self.stencil_usage
} }
/// Returns the sharing the image was created with. /// Returns the sharing the image was created with.
@ -1662,11 +1686,8 @@ impl RawImage {
aspects: { aspects: {
let aspects = self.format.unwrap().aspects(); let aspects = self.format.unwrap().aspects();
if aspects.plane0 { if aspects.intersects(ImageAspects::PLANE_0) {
ImageAspects { ImageAspects::PLANE_0
plane0: true,
..ImageAspects::empty()
}
} else { } else {
aspects aspects
} }
@ -1681,12 +1702,8 @@ impl RawImage {
#[inline] #[inline]
pub fn subresource_range(&self) -> ImageSubresourceRange { pub fn subresource_range(&self) -> ImageSubresourceRange {
ImageSubresourceRange { ImageSubresourceRange {
aspects: ImageAspects { aspects: self.format.unwrap().aspects()
plane0: false, - (ImageAspects::PLANE_0 | ImageAspects::PLANE_1 | ImageAspects::PLANE_2),
plane1: false,
plane2: false,
..self.format.unwrap().aspects()
},
mip_levels: 0..self.mip_levels, mip_levels: 0..self.mip_levels,
array_layers: 0..self.dimensions.array_layers(), array_layers: 0..self.dimensions.array_layers(),
} }
@ -1754,12 +1771,14 @@ impl RawImage {
// VUID-vkGetImageSubresourceLayout-aspectMask-00997 // VUID-vkGetImageSubresourceLayout-aspectMask-00997
// VUID-vkGetImageSubresourceLayout-format-04462 // VUID-vkGetImageSubresourceLayout-format-04462
// VUID-vkGetImageSubresourceLayout-format-04463 // VUID-vkGetImageSubresourceLayout-format-04463
if allowed_aspects.depth && allowed_aspects.stencil { if allowed_aspects.contains(ImageAspects::DEPTH | ImageAspects::STENCIL) {
return Err(ImageError::DepthStencilFormatsNotSupported); return Err(ImageError::DepthStencilFormatsNotSupported);
} }
if allowed_aspects.plane0 || allowed_aspects.plane1 || allowed_aspects.plane2 { if allowed_aspects
allowed_aspects.color = false; .intersects(ImageAspects::PLANE_0 | ImageAspects::PLANE_1 | ImageAspects::PLANE_2)
{
allowed_aspects -= ImageAspects::COLOR;
} }
// VUID-vkGetImageSubresourceLayout-format-04461 // VUID-vkGetImageSubresourceLayout-format-04461
@ -1768,7 +1787,7 @@ impl RawImage {
// VUID-vkGetImageSubresourceLayout-format-04464 // VUID-vkGetImageSubresourceLayout-format-04464
// VUID-vkGetImageSubresourceLayout-format-01581 // VUID-vkGetImageSubresourceLayout-format-01581
// VUID-vkGetImageSubresourceLayout-format-01582 // VUID-vkGetImageSubresourceLayout-format-01582
if !allowed_aspects.contains(&aspect.into()) { if !allowed_aspects.contains(aspect.into()) {
return Err(ImageError::AspectNotAllowed { return Err(ImageError::AspectNotAllowed {
provided_aspect: aspect, provided_aspect: aspect,
allowed_aspects, allowed_aspects,
@ -1997,7 +2016,7 @@ pub enum ImageMemory {
impl Image { impl Image {
fn from_raw(inner: RawImage, memory: ImageMemory) -> Self { fn from_raw(inner: RawImage, memory: ImageMemory) -> Self {
let aspects = inner.format.unwrap().aspects(); let aspects = inner.format.unwrap().aspects();
let aspect_list: SmallVec<[ImageAspect; 4]> = aspects.iter().collect(); let aspect_list: SmallVec<[ImageAspect; 4]> = aspects.into_iter().collect();
let mip_level_size = inner.dimensions.array_layers() as DeviceSize; let mip_level_size = inner.dimensions.array_layers() as DeviceSize;
let aspect_size = mip_level_size * inner.mip_levels as DeviceSize; let aspect_size = mip_level_size * inner.mip_levels as DeviceSize;
let range_size = aspect_list.len() as DeviceSize * aspect_size; let range_size = aspect_list.len() as DeviceSize * aspect_size;
@ -2088,8 +2107,8 @@ impl Image {
/// Returns the features supported by the image's format. /// Returns the features supported by the image's format.
#[inline] #[inline]
pub fn format_features(&self) -> &FormatFeatures { pub fn format_features(&self) -> FormatFeatures {
&self.inner.format_features self.inner.format_features
} }
/// Returns the number of mipmap levels in the image. /// Returns the number of mipmap levels in the image.
@ -2118,14 +2137,14 @@ impl Image {
/// Returns the usage the image was created with. /// Returns the usage the image was created with.
#[inline] #[inline]
pub fn usage(&self) -> &ImageUsage { pub fn usage(&self) -> ImageUsage {
&self.inner.usage self.inner.usage
} }
/// Returns the stencil usage the image was created with. /// Returns the stencil usage the image was created with.
#[inline] #[inline]
pub fn stencil_usage(&self) -> &ImageUsage { pub fn stencil_usage(&self) -> ImageUsage {
&self.inner.stencil_usage self.inner.stencil_usage
} }
/// Returns the sharing the image was created with. /// Returns the sharing the image was created with.
@ -2206,7 +2225,7 @@ impl Image {
.format() .format()
.unwrap() .unwrap()
.aspects() .aspects()
.contains(&subresource_range.aspects)); .contains(subresource_range.aspects));
assert!(subresource_range.mip_levels.end <= self.inner.mip_levels); assert!(subresource_range.mip_levels.end <= self.inner.mip_levels);
assert!(subresource_range.array_layers.end <= self.inner.dimensions.array_layers()); assert!(subresource_range.array_layers.end <= self.inner.dimensions.array_layers());
@ -2608,7 +2627,7 @@ impl SubresourceRangeIterator {
let mut aspect_nums = subresource_range let mut aspect_nums = subresource_range
.aspects .aspects
.iter() .into_iter()
.map(|aspect| image_aspect_list.iter().position(|&a| a == aspect).unwrap()) .map(|aspect| image_aspect_list.iter().position(|&a| a == aspect).unwrap())
.collect::<SmallVec<[usize; 4]>>() .collect::<SmallVec<[usize; 4]>>()
.into_iter() .into_iter()
@ -3239,10 +3258,7 @@ mod tests {
array_layers: 1, array_layers: 1,
}, },
format: Some(Format::R8G8B8A8_UNORM), format: Some(Format::R8G8B8A8_UNORM),
usage: ImageUsage { usage: ImageUsage::SAMPLED,
sampled: true,
..ImageUsage::empty()
},
..Default::default() ..Default::default()
}, },
) )
@ -3262,11 +3278,7 @@ mod tests {
array_layers: 1, array_layers: 1,
}, },
format: Some(Format::R8G8B8A8_UNORM), format: Some(Format::R8G8B8A8_UNORM),
usage: ImageUsage { usage: ImageUsage::TRANSIENT_ATTACHMENT | ImageUsage::COLOR_ATTACHMENT,
transient_attachment: true,
color_attachment: true,
..ImageUsage::empty()
},
..Default::default() ..Default::default()
}, },
) )
@ -3288,10 +3300,7 @@ mod tests {
}, },
format: Some(Format::R8G8B8A8_UNORM), format: Some(Format::R8G8B8A8_UNORM),
mip_levels: 0, mip_levels: 0,
usage: ImageUsage { usage: ImageUsage::SAMPLED,
sampled: true,
..ImageUsage::empty()
},
..Default::default() ..Default::default()
}, },
); );
@ -3312,10 +3321,7 @@ mod tests {
}, },
format: Some(Format::R8G8B8A8_UNORM), format: Some(Format::R8G8B8A8_UNORM),
mip_levels: u32::MAX, mip_levels: u32::MAX,
usage: ImageUsage { usage: ImageUsage::SAMPLED,
sampled: true,
..ImageUsage::empty()
},
..Default::default() ..Default::default()
}, },
); );
@ -3340,10 +3346,7 @@ mod tests {
}, },
format: Some(Format::R8G8B8A8_UNORM), format: Some(Format::R8G8B8A8_UNORM),
samples: SampleCount::Sample2, samples: SampleCount::Sample2,
usage: ImageUsage { usage: ImageUsage::STORAGE,
storage: true,
..ImageUsage::empty()
},
..Default::default() ..Default::default()
}, },
); );
@ -3371,10 +3374,7 @@ mod tests {
array_layers: 1, array_layers: 1,
}, },
format: Some(Format::ASTC_5x4_UNORM_BLOCK), format: Some(Format::ASTC_5x4_UNORM_BLOCK),
usage: ImageUsage { usage: ImageUsage::COLOR_ATTACHMENT,
color_attachment: true,
..ImageUsage::empty()
},
..Default::default() ..Default::default()
}, },
); );
@ -3402,11 +3402,7 @@ mod tests {
array_layers: 1, array_layers: 1,
}, },
format: Some(Format::R8G8B8A8_UNORM), format: Some(Format::R8G8B8A8_UNORM),
usage: ImageUsage { usage: ImageUsage::TRANSIENT_ATTACHMENT | ImageUsage::SAMPLED,
transient_attachment: true,
sampled: true,
..ImageUsage::empty()
},
..Default::default() ..Default::default()
}, },
); );
@ -3420,20 +3416,14 @@ mod tests {
let res = RawImage::new( let res = RawImage::new(
device, device,
ImageCreateInfo { ImageCreateInfo {
flags: ImageCreateFlags { flags: ImageCreateFlags::CUBE_COMPATIBLE,
cube_compatible: true,
..ImageCreateFlags::empty()
},
dimensions: ImageDimensions::Dim2d { dimensions: ImageDimensions::Dim2d {
width: 32, width: 32,
height: 64, height: 64,
array_layers: 1, array_layers: 1,
}, },
format: Some(Format::R8G8B8A8_UNORM), format: Some(Format::R8G8B8A8_UNORM),
usage: ImageUsage { usage: ImageUsage::SAMPLED,
sampled: true,
..ImageUsage::empty()
},
..Default::default() ..Default::default()
}, },
); );
@ -3449,15 +3439,12 @@ mod tests {
#[allow(clippy::erasing_op, clippy::identity_op)] #[allow(clippy::erasing_op, clippy::identity_op)]
fn subresource_range_iterator() { fn subresource_range_iterator() {
// A fictitious set of aspects that no real image would actually ever have. // A fictitious set of aspects that no real image would actually ever have.
let image_aspect_list: SmallVec<[ImageAspect; 4]> = ImageAspects { let image_aspect_list: SmallVec<[ImageAspect; 4]> = (ImageAspects::COLOR
color: true, | ImageAspects::DEPTH
depth: true, | ImageAspects::STENCIL
stencil: true, | ImageAspects::PLANE_0)
plane0: true, .into_iter()
..ImageAspects::empty() .collect();
}
.iter()
.collect();
let image_mip_levels = 6; let image_mip_levels = 6;
let image_array_layers = 8; let image_array_layers = 8;
@ -3467,13 +3454,10 @@ mod tests {
// Whole image // Whole image
let mut iter = SubresourceRangeIterator::new( let mut iter = SubresourceRangeIterator::new(
ImageSubresourceRange { ImageSubresourceRange {
aspects: ImageAspects { aspects: ImageAspects::COLOR
color: true, | ImageAspects::DEPTH
depth: true, | ImageAspects::STENCIL
stencil: true, | ImageAspects::PLANE_0,
plane0: true,
..ImageAspects::empty()
},
mip_levels: 0..6, mip_levels: 0..6,
array_layers: 0..8, array_layers: 0..8,
}, },
@ -3490,13 +3474,7 @@ mod tests {
// Only some aspects // Only some aspects
let mut iter = SubresourceRangeIterator::new( let mut iter = SubresourceRangeIterator::new(
ImageSubresourceRange { ImageSubresourceRange {
aspects: ImageAspects { aspects: ImageAspects::COLOR | ImageAspects::DEPTH | ImageAspects::PLANE_0,
color: true,
depth: true,
stencil: false,
plane0: true,
..ImageAspects::empty()
},
mip_levels: 0..6, mip_levels: 0..6,
array_layers: 0..8, array_layers: 0..8,
}, },
@ -3514,13 +3492,7 @@ mod tests {
// Two aspects, and only some of the mip levels // Two aspects, and only some of the mip levels
let mut iter = SubresourceRangeIterator::new( let mut iter = SubresourceRangeIterator::new(
ImageSubresourceRange { ImageSubresourceRange {
aspects: ImageAspects { aspects: ImageAspects::DEPTH | ImageAspects::STENCIL,
color: false,
depth: true,
stencil: true,
plane0: false,
..ImageAspects::empty()
},
mip_levels: 2..4, mip_levels: 2..4,
array_layers: 0..8, array_layers: 0..8,
}, },
@ -3537,13 +3509,8 @@ mod tests {
// One aspect, one mip level, only some of the array layers // One aspect, one mip level, only some of the array layers
let mut iter = SubresourceRangeIterator::new( let mut iter = SubresourceRangeIterator::new(
ImageSubresourceRange { ImageSubresourceRange {
aspects: ImageAspects { aspects: ImageAspects::COLOR,
color: true,
depth: false,
stencil: false,
plane0: false,
..ImageAspects::empty()
},
mip_levels: 0..1, mip_levels: 0..1,
array_layers: 2..4, array_layers: 2..4,
}, },
@ -3563,13 +3530,7 @@ mod tests {
// Two aspects, two mip levels, only some of the array layers // Two aspects, two mip levels, only some of the array layers
let mut iter = SubresourceRangeIterator::new( let mut iter = SubresourceRangeIterator::new(
ImageSubresourceRange { ImageSubresourceRange {
aspects: ImageAspects { aspects: ImageAspects::DEPTH | ImageAspects::STENCIL,
color: false,
depth: true,
stencil: true,
plane0: false,
..ImageAspects::empty()
},
mip_levels: 2..4, mip_levels: 2..4,
array_layers: 6..8, array_layers: 6..8,
}, },

View File

@ -75,7 +75,7 @@ pub unsafe trait ImageAccess: DeviceOwned + Send + Sync {
/// Returns the features supported by the image's format. /// Returns the features supported by the image's format.
#[inline] #[inline]
fn format_features(&self) -> &FormatFeatures { fn format_features(&self) -> FormatFeatures {
self.inner().image.format_features() self.inner().image.format_features()
} }
@ -93,13 +93,13 @@ pub unsafe trait ImageAccess: DeviceOwned + Send + Sync {
/// Returns the usage the image was created with. /// Returns the usage the image was created with.
#[inline] #[inline]
fn usage(&self) -> &ImageUsage { fn usage(&self) -> ImageUsage {
self.inner().image.usage() self.inner().image.usage()
} }
/// Returns the stencil usage the image was created with. /// Returns the stencil usage the image was created with.
#[inline] #[inline]
fn stencil_usage(&self) -> &ImageUsage { fn stencil_usage(&self) -> ImageUsage {
self.inner().image.stencil_usage() self.inner().image.stencil_usage()
} }
@ -115,12 +115,8 @@ pub unsafe trait ImageAccess: DeviceOwned + Send + Sync {
#[inline] #[inline]
fn subresource_range(&self) -> ImageSubresourceRange { fn subresource_range(&self) -> ImageSubresourceRange {
ImageSubresourceRange { ImageSubresourceRange {
aspects: ImageAspects { aspects: self.format().aspects()
plane0: false, - (ImageAspects::PLANE_0 | ImageAspects::PLANE_1 | ImageAspects::PLANE_2),
plane1: false,
plane2: false,
..self.format().aspects()
},
mip_levels: 0..self.mip_levels(), mip_levels: 0..self.mip_levels(),
array_layers: 0..self.dimensions().array_layers(), array_layers: 0..self.dimensions().array_layers(),
} }

View File

@ -10,29 +10,30 @@
use crate::macros::vulkan_bitflags; use crate::macros::vulkan_bitflags;
vulkan_bitflags! { vulkan_bitflags! {
#[non_exhaustive]
/// Describes how an image is going to be used. This is **not** just an optimization. /// Describes how an image is going to be used. This is **not** just an optimization.
/// ///
/// If you try to use an image in a way that you didn't declare, an error will occur. /// If you try to use an image in a way that you didn't declare, an error will occur.
#[non_exhaustive]
ImageUsage = ImageUsageFlags(u32); ImageUsage = ImageUsageFlags(u32);
/// The image can be used as a source for transfer, blit, resolve and clear commands. /// The image can be used as a source for transfer, blit, resolve and clear commands.
transfer_src = TRANSFER_SRC, TRANSFER_SRC = TRANSFER_SRC,
/// The image can be used as a destination for transfer, blit, resolve and clear commands. /// The image can be used as a destination for transfer, blit, resolve and clear commands.
transfer_dst = TRANSFER_DST, TRANSFER_DST = TRANSFER_DST,
/// The image can be used as a sampled image in a shader. /// The image can be used as a sampled image in a shader.
sampled = SAMPLED, SAMPLED = SAMPLED,
/// The image can be used as a storage image in a shader. /// The image can be used as a storage image in a shader.
storage = STORAGE, STORAGE = STORAGE,
/// The image can be used as a color attachment in a render pass/framebuffer. /// The image can be used as a color attachment in a render pass/framebuffer.
color_attachment = COLOR_ATTACHMENT, COLOR_ATTACHMENT = COLOR_ATTACHMENT,
/// The image can be used as a depth/stencil attachment in a render pass/framebuffer. /// The image can be used as a depth/stencil attachment in a render pass/framebuffer.
depth_stencil_attachment = DEPTH_STENCIL_ATTACHMENT, DEPTH_STENCIL_ATTACHMENT = DEPTH_STENCIL_ATTACHMENT,
/// The image will be used as an attachment, and will only ever be used temporarily. /// The image will be used as an attachment, and will only ever be used temporarily.
/// As soon as you leave a render pass, the content of transient images becomes undefined. /// As soon as you leave a render pass, the content of transient images becomes undefined.
@ -43,54 +44,54 @@ vulkan_bitflags! {
/// If `transient_attachment` is true, then only `color_attachment`, `depth_stencil_attachment` /// If `transient_attachment` is true, then only `color_attachment`, `depth_stencil_attachment`
/// and `input_attachment` can be true as well. The rest must be false or an error will be /// and `input_attachment` can be true as well. The rest must be false or an error will be
/// returned when creating the image. /// returned when creating the image.
transient_attachment = TRANSIENT_ATTACHMENT, TRANSIENT_ATTACHMENT = TRANSIENT_ATTACHMENT,
/// The image can be used as an input attachment in a render pass/framebuffer. /// The image can be used as an input attachment in a render pass/framebuffer.
input_attachment = INPUT_ATTACHMENT, INPUT_ATTACHMENT = INPUT_ATTACHMENT,
/* /*
// TODO: document // TODO: document
video_decode_dst = VIDEO_DECODE_DST_KHR { VIDEO_DECODE_DST = VIDEO_DECODE_DST_KHR {
device_extensions: [khr_video_decode_queue], device_extensions: [khr_video_decode_queue],
}, },
// TODO: document // TODO: document
video_decode_src = VIDEO_DECODE_SRC_KHR { VIDEO_DECODE_SRC = VIDEO_DECODE_SRC_KHR {
device_extensions: [khr_video_decode_queue], device_extensions: [khr_video_decode_queue],
}, },
// TODO: document // TODO: document
video_decode_dpb = VIDEO_DECODE_DPB_KHR { VIDEO_DECODE_DPB = VIDEO_DECODE_DPB_KHR {
device_extensions: [khr_video_decode_queue], device_extensions: [khr_video_decode_queue],
}, },
// TODO: document // TODO: document
fragment_density_map = FRAGMENT_DENSITY_MAP_EXT { FRAGMENT_DENSITY_MAP = FRAGMENT_DENSITY_MAP_EXT {
device_extensions: [ext_fragment_density_map], device_extensions: [ext_fragment_density_map],
}, },
// TODO: document // TODO: document
fragment_shading_rate_attachment = FRAGMENT_SHADING_RATE_ATTACHMENT_KHR { FRAGMENT_SHADING_RATE_ATTACHMENT = FRAGMENT_SHADING_RATE_ATTACHMENT_KHR {
device_extensions: [khr_fragment_shading_rate], device_extensions: [khr_fragment_shading_rate],
}, },
// TODO: document // TODO: document
video_encode_dst = VIDEO_ENCODE_DST_KHR { VIDEO_ENCODE_DST = VIDEO_ENCODE_DST_KHR {
device_extensions: [khr_video_encode_queue], device_extensions: [khr_video_encode_queue],
}, },
// TODO: document // TODO: document
video_encode_src = VIDEO_ENCODE_SRC_KHR { VIDEO_ENCODE_SRC = VIDEO_ENCODE_SRC_KHR {
device_extensions: [khr_video_encode_queue], device_extensions: [khr_video_encode_queue],
}, },
// TODO: document // TODO: document
video_encode_dpb = VIDEO_ENCODE_DPB_KHR { VIDEO_ENCODE_DPB = VIDEO_ENCODE_DPB_KHR {
device_extensions: [khr_video_encode_queue], device_extensions: [khr_video_encode_queue],
}, },
// TODO: document // TODO: document
invocation_mask = INVOCATION_MASK_HUAWEI { INVOCATION_MASK = INVOCATION_MASK_HUAWEI {
device_extensions: [huawei_invocation_mask], device_extensions: [huawei_invocation_mask],
}, },
*/ */

View File

@ -19,7 +19,7 @@ use super::{
use crate::{ use crate::{
device::{Device, DeviceOwned}, device::{Device, DeviceOwned},
format::{ChromaSampling, Format, FormatFeatures}, format::{ChromaSampling, Format, FormatFeatures},
image::{ImageAspects, ImageTiling, ImageType, SampleCount}, image::{ImageAspects, ImageCreateFlags, ImageTiling, ImageType, SampleCount},
macros::vulkan_enum, macros::vulkan_enum,
sampler::{ycbcr::SamplerYcbcrConversion, ComponentMapping}, sampler::{ycbcr::SamplerYcbcrConversion, ComponentMapping},
OomError, RequirementNotMet, RequiresOneOf, Version, VulkanError, VulkanObject, OomError, RequirementNotMet, RequiresOneOf, Version, VulkanError, VulkanObject,
@ -145,32 +145,24 @@ where
// VUID-VkImageSubresourceRange-aspectMask-parameter // VUID-VkImageSubresourceRange-aspectMask-parameter
subresource_range.aspects.validate_device(device)?; subresource_range.aspects.validate_device(device)?;
{ assert!(!subresource_range.aspects.intersects(
let ImageAspects { ImageAspects::METADATA
color, | ImageAspects::MEMORY_PLANE_0
depth, | ImageAspects::MEMORY_PLANE_1
stencil, | ImageAspects::MEMORY_PLANE_2
metadata, ));
plane0, assert!({
plane1, subresource_range.aspects.count() == 1
plane2, || subresource_range
memory_plane0, .aspects
memory_plane1, .contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
memory_plane2, && !subresource_range.aspects.intersects(
_ne: _, ImageAspects::COLOR
} = subresource_range.aspects; | ImageAspects::PLANE_0
| ImageAspects::PLANE_1
assert!(!(metadata || memory_plane0 || memory_plane1 || memory_plane2)); | ImageAspects::PLANE_2,
assert!({ )
let num_bits = color as u8 });
+ depth as u8
+ stencil as u8
+ plane0 as u8
+ plane1 as u8
+ plane2 as u8;
num_bits == 1 || depth && stencil && !(color || plane0 || plane1 || plane2)
});
}
// Get format features // Get format features
let format_features = unsafe { Self::get_format_features(format, image_inner) }; let format_features = unsafe { Self::get_format_features(format, image_inner) };
@ -180,7 +172,7 @@ where
.format() .format()
.unwrap() .unwrap()
.aspects() .aspects()
.contains(&subresource_range.aspects) .contains(subresource_range.aspects)
{ {
return Err(ImageViewCreationError::ImageAspectsNotCompatible { return Err(ImageViewCreationError::ImageAspectsNotCompatible {
aspects: subresource_range.aspects, aspects: subresource_range.aspects,
@ -203,7 +195,9 @@ where
// VUID-VkImageViewCreateInfo-image-01003 // VUID-VkImageViewCreateInfo-image-01003
if (view_type == ImageViewType::Cube || view_type == ImageViewType::CubeArray) if (view_type == ImageViewType::Cube || view_type == ImageViewType::CubeArray)
&& !image_inner.flags().cube_compatible && !image_inner
.flags()
.intersects(ImageCreateFlags::CUBE_COMPATIBLE)
{ {
return Err(ImageViewCreationError::ImageNotCubeCompatible); return Err(ImageViewCreationError::ImageNotCubeCompatible);
} }
@ -231,7 +225,10 @@ where
&& (view_type == ImageViewType::Dim2d || view_type == ImageViewType::Dim2dArray) && (view_type == ImageViewType::Dim2d || view_type == ImageViewType::Dim2dArray)
{ {
// VUID-VkImageViewCreateInfo-image-01005 // VUID-VkImageViewCreateInfo-image-01005
if !image_inner.flags().array_2d_compatible { if !image_inner
.flags()
.intersects(ImageCreateFlags::ARRAY_2D_COMPATIBLE)
{
return Err(ImageViewCreationError::ImageNotArray2dCompatible); return Err(ImageViewCreationError::ImageNotArray2dCompatible);
} }
@ -299,7 +296,7 @@ where
// VUID-VkImageViewCreateInfo-pNext-02662 // VUID-VkImageViewCreateInfo-pNext-02662
// VUID-VkImageViewCreateInfo-pNext-02663 // VUID-VkImageViewCreateInfo-pNext-02663
// VUID-VkImageViewCreateInfo-pNext-02664 // VUID-VkImageViewCreateInfo-pNext-02664
if !default_usage.contains(&usage) { if !default_usage.contains(usage) {
return Err(ImageViewCreationError::UsageNotSupportedByImage { return Err(ImageViewCreationError::UsageNotSupportedByImage {
usage, usage,
supported_usage: default_usage, supported_usage: default_usage,
@ -308,43 +305,54 @@ where
} }
// VUID-VkImageViewCreateInfo-image-04441 // VUID-VkImageViewCreateInfo-image-04441
if !(image_inner.usage().sampled if !image_inner.usage().intersects(
|| image_inner.usage().storage ImageUsage::SAMPLED
|| image_inner.usage().color_attachment | ImageUsage::STORAGE
|| image_inner.usage().depth_stencil_attachment | ImageUsage::COLOR_ATTACHMENT
|| image_inner.usage().input_attachment | ImageUsage::DEPTH_STENCIL_ATTACHMENT
|| image_inner.usage().transient_attachment) | ImageUsage::INPUT_ATTACHMENT
{ | ImageUsage::TRANSIENT_ATTACHMENT,
) {
return Err(ImageViewCreationError::ImageMissingUsage); return Err(ImageViewCreationError::ImageMissingUsage);
} }
// VUID-VkImageViewCreateInfo-usage-02274 // VUID-VkImageViewCreateInfo-usage-02274
if usage.sampled && !format_features.sampled_image { if usage.intersects(ImageUsage::SAMPLED)
&& !format_features.intersects(FormatFeatures::SAMPLED_IMAGE)
{
return Err(ImageViewCreationError::FormatUsageNotSupported { usage: "sampled" }); return Err(ImageViewCreationError::FormatUsageNotSupported { usage: "sampled" });
} }
// VUID-VkImageViewCreateInfo-usage-02275 // VUID-VkImageViewCreateInfo-usage-02275
if usage.storage && !format_features.storage_image { if usage.intersects(ImageUsage::STORAGE)
&& !format_features.intersects(FormatFeatures::STORAGE_IMAGE)
{
return Err(ImageViewCreationError::FormatUsageNotSupported { usage: "storage" }); return Err(ImageViewCreationError::FormatUsageNotSupported { usage: "storage" });
} }
// VUID-VkImageViewCreateInfo-usage-02276 // VUID-VkImageViewCreateInfo-usage-02276
if usage.color_attachment && !format_features.color_attachment { if usage.intersects(ImageUsage::COLOR_ATTACHMENT)
&& !format_features.intersects(FormatFeatures::COLOR_ATTACHMENT)
{
return Err(ImageViewCreationError::FormatUsageNotSupported { return Err(ImageViewCreationError::FormatUsageNotSupported {
usage: "color_attachment", usage: "color_attachment",
}); });
} }
// VUID-VkImageViewCreateInfo-usage-02277 // VUID-VkImageViewCreateInfo-usage-02277
if usage.depth_stencil_attachment && !format_features.depth_stencil_attachment { if usage.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
&& !format_features.intersects(FormatFeatures::DEPTH_STENCIL_ATTACHMENT)
{
return Err(ImageViewCreationError::FormatUsageNotSupported { return Err(ImageViewCreationError::FormatUsageNotSupported {
usage: "depth_stencil_attachment", usage: "depth_stencil_attachment",
}); });
} }
// VUID-VkImageViewCreateInfo-usage-02652 // VUID-VkImageViewCreateInfo-usage-02652
if usage.input_attachment if usage.intersects(ImageUsage::INPUT_ATTACHMENT)
&& !(format_features.color_attachment || format_features.depth_stencil_attachment) && !format_features.intersects(
FormatFeatures::COLOR_ATTACHMENT | FormatFeatures::DEPTH_STENCIL_ATTACHMENT,
)
{ {
return Err(ImageViewCreationError::FormatUsageNotSupported { return Err(ImageViewCreationError::FormatUsageNotSupported {
usage: "input_attachment", usage: "input_attachment",
@ -355,9 +363,11 @@ where
if Some(format) != image_inner.format() { if Some(format) != image_inner.format() {
// VUID-VkImageViewCreateInfo-image-01762 // VUID-VkImageViewCreateInfo-image-01762
if !image_inner.flags().mutable_format if !image_inner
.flags()
.intersects(ImageCreateFlags::MUTABLE_FORMAT)
|| !image_inner.format().unwrap().planes().is_empty() || !image_inner.format().unwrap().planes().is_empty()
&& subresource_range.aspects.color && subresource_range.aspects.intersects(ImageAspects::COLOR)
{ {
return Err(ImageViewCreationError::FormatNotCompatible); return Err(ImageViewCreationError::FormatNotCompatible);
} }
@ -370,10 +380,9 @@ where
&& format.components() != image_inner.format().unwrap().components() && format.components() != image_inner.format().unwrap().components()
{ {
return Err(ImageViewCreationError::RequirementNotMet { return Err(ImageViewCreationError::RequirementNotMet {
required_for: required_for: "this device is a portability subset device, and the format of \
"this device is a portability subset device, and the format of the image \ the image view does not have the same components and number of bits per \
view does not have the same components and number of bits per component as \ component as the parent image",
the parent image",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["image_view_format_reinterpretation"], features: &["image_view_format_reinterpretation"],
..Default::default() ..Default::default()
@ -381,7 +390,10 @@ where
}); });
} }
if image_inner.flags().block_texel_view_compatible { if image_inner
.flags()
.intersects(ImageCreateFlags::BLOCK_TEXEL_VIEW_COMPATIBLE)
{
// VUID-VkImageViewCreateInfo-image-01583 // VUID-VkImageViewCreateInfo-image-01583
if !(format.compatibility() == image_inner.format().unwrap().compatibility() if !(format.compatibility() == image_inner.format().unwrap().compatibility()
|| format.block_size() == image_inner.format().unwrap().block_size()) || format.block_size() == image_inner.format().unwrap().block_size())
@ -411,11 +423,11 @@ where
return Err(ImageViewCreationError::FormatNotCompatible); return Err(ImageViewCreationError::FormatNotCompatible);
} }
} else { } else {
let plane = if subresource_range.aspects.plane0 { let plane = if subresource_range.aspects.intersects(ImageAspects::PLANE_0) {
0 0
} else if subresource_range.aspects.plane1 { } else if subresource_range.aspects.intersects(ImageAspects::PLANE_1) {
1 1
} else if subresource_range.aspects.plane2 { } else if subresource_range.aspects.intersects(ImageAspects::PLANE_2) {
2 2
} else { } else {
unreachable!() unreachable!()
@ -660,7 +672,7 @@ where
format: image_inner.format(), format: image_inner.format(),
image_type: image.dimensions().image_type(), image_type: image.dimensions().image_type(),
tiling: image_inner.tiling(), tiling: image_inner.tiling(),
usage: *image_inner.usage(), usage: image_inner.usage(),
image_view_type: Some(view_type), image_view_type: Some(view_type),
..Default::default() ..Default::default()
})?; })?;
@ -689,19 +701,15 @@ where
// https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VkImageViewCreateInfo.html#_description // https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VkImageViewCreateInfo.html#_description
fn get_default_usage(aspects: ImageAspects, image: &Image) -> ImageUsage { fn get_default_usage(aspects: ImageAspects, image: &Image) -> ImageUsage {
let has_stencil_aspect = aspects.stencil; let has_stencil_aspect = aspects.intersects(ImageAspects::STENCIL);
let has_non_stencil_aspect = !(ImageAspects { let has_non_stencil_aspect = !(aspects - ImageAspects::STENCIL).is_empty();
stencil: false,
..aspects
})
.is_empty();
if has_stencil_aspect && has_non_stencil_aspect { if has_stencil_aspect && has_non_stencil_aspect {
*image.usage() & *image.stencil_usage() image.usage() & image.stencil_usage()
} else if has_stencil_aspect { } else if has_stencil_aspect {
*image.stencil_usage() image.stencil_usage()
} else if has_non_stencil_aspect { } else if has_non_stencil_aspect {
*image.usage() image.usage()
} else { } else {
unreachable!() unreachable!()
} }
@ -711,7 +719,7 @@ where
unsafe fn get_format_features(format: Format, image: &Image) -> FormatFeatures { unsafe fn get_format_features(format: Format, image: &Image) -> FormatFeatures {
let device = image.device(); let device = image.device();
let format_features = if Some(format) != image.format() { let mut format_features = if Some(format) != image.format() {
// Use unchecked, because all validation should have been done before calling. // Use unchecked, because all validation should have been done before calling.
let format_properties = device.physical_device().format_properties_unchecked(format); let format_properties = device.physical_device().format_properties_unchecked(format);
@ -720,28 +728,34 @@ where
ImageTiling::Linear => format_properties.linear_tiling_features, ImageTiling::Linear => format_properties.linear_tiling_features,
} }
} else { } else {
*image.format_features() image.format_features()
}; };
if device.enabled_extensions().khr_format_feature_flags2 { if !device.enabled_extensions().khr_format_feature_flags2 {
format_features if format.type_color().is_none()
} else { && format_features.intersects(FormatFeatures::SAMPLED_IMAGE)
let is_without_format = format.shader_storage_image_without_format(); {
format_features |= FormatFeatures::SAMPLED_IMAGE_DEPTH_COMPARISON;
}
FormatFeatures { if format.shader_storage_image_without_format() {
sampled_image_depth_comparison: format.type_color().is_none() if device
&& format_features.sampled_image, .enabled_features()
storage_read_without_format: is_without_format .shader_storage_image_read_without_format
&& device {
.enabled_features() format_features |= FormatFeatures::STORAGE_READ_WITHOUT_FORMAT;
.shader_storage_image_read_without_format, }
storage_write_without_format: is_without_format
&& device if device
.enabled_features() .enabled_features()
.shader_storage_image_write_without_format, .shader_storage_image_write_without_format
..format_features {
format_features |= FormatFeatures::STORAGE_WRITE_WITHOUT_FORMAT;
}
} }
} }
format_features
} }
/// Returns the wrapped image that this image view was created from. /// Returns the wrapped image that this image view was created from.
@ -1146,9 +1160,38 @@ impl From<RequirementNotMet> for ImageViewCreationError {
} }
vulkan_enum! { vulkan_enum! {
/// The geometry type of an image view.
#[non_exhaustive] #[non_exhaustive]
ImageViewType = ImageViewType(i32);
/// The geometry type of an image view.
ImageViewType impl {
/// Returns whether the type is arrayed.
#[inline]
pub fn is_arrayed(self) -> bool {
match self {
Self::Dim1d | Self::Dim2d | Self::Dim3d | Self::Cube => false,
Self::Dim1dArray | Self::Dim2dArray | Self::CubeArray => true,
}
}
/// Returns whether `self` is compatible with the given `image_type`.
#[inline]
pub fn is_compatible_with(self, image_type: ImageType) -> bool {
matches!(
(self, image_type,),
(
ImageViewType::Dim1d | ImageViewType::Dim1dArray,
ImageType::Dim1d
) | (
ImageViewType::Dim2d | ImageViewType::Dim2dArray,
ImageType::Dim2d | ImageType::Dim3d
) | (
ImageViewType::Cube | ImageViewType::CubeArray,
ImageType::Dim2d
) | (ImageViewType::Dim3d, ImageType::Dim3d)
)
}
}
= ImageViewType(i32);
// TODO: document // TODO: document
Dim1d = TYPE_1D, Dim1d = TYPE_1D,
@ -1172,35 +1215,6 @@ vulkan_enum! {
CubeArray = CUBE_ARRAY, CubeArray = CUBE_ARRAY,
} }
impl ImageViewType {
/// Returns whether the type is arrayed.
#[inline]
pub fn is_arrayed(&self) -> bool {
match self {
Self::Dim1d | Self::Dim2d | Self::Dim3d | Self::Cube => false,
Self::Dim1dArray | Self::Dim2dArray | Self::CubeArray => true,
}
}
/// Returns whether `self` is compatible with the given `image_type`.
#[inline]
pub fn is_compatible_with(&self, image_type: ImageType) -> bool {
matches!(
(*self, image_type,),
(
ImageViewType::Dim1d | ImageViewType::Dim1dArray,
ImageType::Dim1d
) | (
ImageViewType::Dim2d | ImageViewType::Dim2dArray,
ImageType::Dim2d | ImageType::Dim3d
) | (
ImageViewType::Cube | ImageViewType::CubeArray,
ImageType::Dim2d
) | (ImageViewType::Dim3d, ImageType::Dim3d)
)
}
}
/// Trait for types that represent the GPU can access an image view. /// Trait for types that represent the GPU can access an image view.
pub unsafe trait ImageViewAbstract: pub unsafe trait ImageViewAbstract:
VulkanObject<Handle = ash::vk::ImageView> + DeviceOwned + Debug + Send + Sync VulkanObject<Handle = ash::vk::ImageView> + DeviceOwned + Debug + Send + Sync
@ -1254,7 +1268,7 @@ pub unsafe trait ImageViewAbstract:
fn format(&self) -> Option<Format>; fn format(&self) -> Option<Format>;
/// Returns the features supported by the image view's format. /// Returns the features supported by the image view's format.
fn format_features(&self) -> &FormatFeatures; fn format_features(&self) -> FormatFeatures;
/// Returns the sampler YCbCr conversion that this image view was created with, if any. /// Returns the sampler YCbCr conversion that this image view was created with, if any.
fn sampler_ycbcr_conversion(&self) -> Option<&Arc<SamplerYcbcrConversion>>; fn sampler_ycbcr_conversion(&self) -> Option<&Arc<SamplerYcbcrConversion>>;
@ -1263,7 +1277,7 @@ pub unsafe trait ImageViewAbstract:
fn subresource_range(&self) -> &ImageSubresourceRange; fn subresource_range(&self) -> &ImageSubresourceRange;
/// Returns the usage of the image view. /// Returns the usage of the image view.
fn usage(&self) -> &ImageUsage; fn usage(&self) -> ImageUsage;
/// Returns the [`ImageViewType`] of this image view. /// Returns the [`ImageViewType`] of this image view.
fn view_type(&self) -> ImageViewType; fn view_type(&self) -> ImageViewType;
@ -1293,8 +1307,8 @@ where
self.format self.format
} }
fn format_features(&self) -> &FormatFeatures { fn format_features(&self) -> FormatFeatures {
&self.format_features self.format_features
} }
fn sampler_ycbcr_conversion(&self) -> Option<&Arc<SamplerYcbcrConversion>> { fn sampler_ycbcr_conversion(&self) -> Option<&Arc<SamplerYcbcrConversion>> {
@ -1305,8 +1319,8 @@ where
&self.subresource_range &self.subresource_range
} }
fn usage(&self) -> &ImageUsage { fn usage(&self) -> ImageUsage {
&self.usage self.usage
} }
fn view_type(&self) -> ImageViewType { fn view_type(&self) -> ImageViewType {
@ -1341,8 +1355,8 @@ unsafe impl ImageViewAbstract for ImageView<dyn ImageAccess> {
} }
#[inline] #[inline]
fn format_features(&self) -> &FormatFeatures { fn format_features(&self) -> FormatFeatures {
&self.format_features self.format_features
} }
#[inline] #[inline]
@ -1356,8 +1370,8 @@ unsafe impl ImageViewAbstract for ImageView<dyn ImageAccess> {
} }
#[inline] #[inline]
fn usage(&self) -> &ImageUsage { fn usage(&self) -> ImageUsage {
&self.usage self.usage
} }
#[inline] #[inline]

View File

@ -105,7 +105,7 @@ impl DebugUtilsMessenger {
if !instance.enabled_extensions().ext_debug_utils { if !instance.enabled_extensions().ext_debug_utils {
return Err(DebugUtilsMessengerCreationError::RequirementNotMet { return Err(DebugUtilsMessengerCreationError::RequirementNotMet {
required_for: "`DebugUtilsMessenger`", required_for: "`DebugUtilsMessenger::new`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
instance_extensions: &["ext_debug_utils"], instance_extensions: &["ext_debug_utils"],
..Default::default() ..Default::default()
@ -319,15 +319,8 @@ impl DebugUtilsMessengerCreateInfo {
#[inline] #[inline]
pub fn user_callback(user_callback: UserCallback) -> Self { pub fn user_callback(user_callback: UserCallback) -> Self {
Self { Self {
message_severity: DebugUtilsMessageSeverity { message_severity: DebugUtilsMessageSeverity::ERROR | DebugUtilsMessageSeverity::WARNING,
error: true, message_type: DebugUtilsMessageType::GENERAL,
warning: true,
..DebugUtilsMessageSeverity::empty()
},
message_type: DebugUtilsMessageType {
general: true,
..DebugUtilsMessageType::empty()
},
user_callback, user_callback,
_ne: crate::NonExhaustive(()), _ne: crate::NonExhaustive(()),
} }
@ -363,36 +356,38 @@ pub struct Message<'a> {
} }
vulkan_bitflags! { vulkan_bitflags! {
/// Severity of message.
#[non_exhaustive] #[non_exhaustive]
/// Severity of message.
DebugUtilsMessageSeverity = DebugUtilsMessageSeverityFlagsEXT(u32); DebugUtilsMessageSeverity = DebugUtilsMessageSeverityFlagsEXT(u32);
/// An error that may cause undefined results, including an application crash. /// An error that may cause undefined results, including an application crash.
error = ERROR, ERROR = ERROR,
/// An unexpected use. /// An unexpected use.
warning = WARNING, WARNING = WARNING,
/// An informational message that may be handy when debugging an application. /// An informational message that may be handy when debugging an application.
information = INFO, INFO = INFO,
/// Diagnostic information from the loader and layers. /// Diagnostic information from the loader and layers.
verbose = VERBOSE, VERBOSE = VERBOSE,
} }
vulkan_bitflags! { vulkan_bitflags! {
/// Type of message.
#[non_exhaustive] #[non_exhaustive]
/// Type of message.
DebugUtilsMessageType = DebugUtilsMessageTypeFlagsEXT(u32); DebugUtilsMessageType = DebugUtilsMessageTypeFlagsEXT(u32);
/// Specifies that some general event has occurred. /// Specifies that some general event has occurred.
general = GENERAL, GENERAL = GENERAL,
/// Specifies that something has occurred during validation against the vulkan specification /// Specifies that something has occurred during validation against the vulkan specification
validation = VALIDATION, VALIDATION = VALIDATION,
/// Specifies a potentially non-optimal use of Vulkan /// Specifies a potentially non-optimal use of Vulkan
performance = PERFORMANCE, PERFORMANCE = PERFORMANCE,
} }
/// A label to associate with a span of work in a queue. /// A label to associate with a span of work in a queue.
@ -428,6 +423,8 @@ impl Default for DebugUtilsLabel {
} }
vulkan_enum! { vulkan_enum! {
#[non_exhaustive]
/// Features of the validation layer to enable. /// Features of the validation layer to enable.
ValidationFeatureEnable = ValidationFeatureEnableEXT(i32); ValidationFeatureEnable = ValidationFeatureEnableEXT(i32);
@ -461,6 +458,8 @@ vulkan_enum! {
} }
vulkan_enum! { vulkan_enum! {
#[non_exhaustive]
/// Features of the validation layer to disable. /// Features of the validation layer to disable.
ValidationFeatureDisable = ValidationFeatureDisableEXT(i32); ValidationFeatureDisable = ValidationFeatureDisableEXT(i32);
@ -529,16 +528,10 @@ mod tests {
DebugUtilsMessenger::new( DebugUtilsMessenger::new(
instance, instance,
DebugUtilsMessengerCreateInfo { DebugUtilsMessengerCreateInfo {
message_severity: DebugUtilsMessageSeverity { message_severity: DebugUtilsMessageSeverity::ERROR,
error: true, message_type: DebugUtilsMessageType::GENERAL
..DebugUtilsMessageSeverity::empty() | DebugUtilsMessageType::VALIDATION
}, | DebugUtilsMessageType::PERFORMANCE,
message_type: DebugUtilsMessageType {
general: true,
validation: true,
performance: true,
..DebugUtilsMessageType::empty()
},
..DebugUtilsMessengerCreateInfo::user_callback(Arc::new(|_| {})) ..DebugUtilsMessengerCreateInfo::user_callback(Arc::new(|_| {}))
}, },
) )

View File

@ -414,7 +414,8 @@ impl Instance {
if !enabled_validation_features.is_empty() || !disabled_validation_features.is_empty() { if !enabled_validation_features.is_empty() || !disabled_validation_features.is_empty() {
if !enabled_extensions.ext_validation_features { if !enabled_extensions.ext_validation_features {
return Err(InstanceCreationError::RequirementNotMet { return Err(InstanceCreationError::RequirementNotMet {
required_for: "`enabled_validation_features` or `disabled_validation_features` are not empty", required_for: "`create_info.enabled_validation_features` or \
`create_info.disabled_validation_features` are not empty",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
instance_extensions: &["ext_validation_features"], instance_extensions: &["ext_validation_features"],
..Default::default() ..Default::default()
@ -464,7 +465,7 @@ impl Instance {
// VUID-VkInstanceCreateInfo-pNext-04926 // VUID-VkInstanceCreateInfo-pNext-04926
if !enabled_extensions.ext_debug_utils { if !enabled_extensions.ext_debug_utils {
return Err(InstanceCreationError::RequirementNotMet { return Err(InstanceCreationError::RequirementNotMet {
required_for: "`debug_utils_messengers` is not empty", required_for: "`create_info.debug_utils_messengers` is not empty",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
instance_extensions: &["ext_debug_utils"], instance_extensions: &["ext_debug_utils"],
..Default::default() ..Default::default()

View File

@ -62,7 +62,11 @@
//! //!
//#![warn(missing_docs)] // TODO: activate //#![warn(missing_docs)] // TODO: activate
#![warn(rust_2018_idioms, rust_2021_compatibility)] #![warn(
rust_2018_idioms,
rust_2021_compatibility,
clippy::trivially_copy_pass_by_ref
)]
// These lints are a bit too pedantic, so they're disabled here. // These lints are a bit too pedantic, so they're disabled here.
#![allow( #![allow(
clippy::collapsible_else_if, clippy::collapsible_else_if,

View File

@ -10,7 +10,9 @@
macro_rules! vulkan_bitflags { macro_rules! vulkan_bitflags {
{ {
$(#[doc = $ty_doc:literal])* $(#[doc = $ty_doc:literal])*
$ty:ident = $ty_ffi:ident($repr:ty); $ty:ident
$( impl { $($impls:item)* } )?
= $ty_ffi:ident($repr:ty);
$( $(
$(#[doc = $flag_doc:literal])* $(#[doc = $flag_doc:literal])*
@ -18,23 +20,19 @@ macro_rules! vulkan_bitflags {
)+ )+
} => { } => {
$(#[doc = $ty_doc])* $(#[doc = $ty_doc])*
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct $ty { pub struct $ty($repr);
$(
$(#[doc = $flag_doc])*
pub $flag_name: bool,
)+
}
impl $ty { impl $ty {
$(
$(#[doc = $flag_doc])*
pub const $flag_name: Self = Self(ash::vk::$ty_ffi::$flag_name_ffi.as_raw());
)*
#[doc = concat!("Returns a `", stringify!($ty), "` with none of the flags set.")] #[doc = concat!("Returns a `", stringify!($ty), "` with none of the flags set.")]
#[inline] #[inline]
pub const fn empty() -> Self { pub const fn empty() -> Self {
Self { Self(0)
$(
$flag_name: false,
)+
}
} }
#[deprecated(since = "0.31.0", note = "Use `empty` instead.")] #[deprecated(since = "0.31.0", note = "Use `empty` instead.")]
@ -47,120 +45,109 @@ macro_rules! vulkan_bitflags {
#[doc = concat!("Returns a `", stringify!($ty), "` with all of the flags set.")] #[doc = concat!("Returns a `", stringify!($ty), "` with all of the flags set.")]
#[inline] #[inline]
pub const fn all() -> Self { pub const fn all() -> Self {
Self { Self(Self::all_raw())
$( }
$flag_name: true,
)+ const fn all_raw() -> $repr {
} 0
$(
| ash::vk::$ty_ffi::$flag_name_ffi.as_raw()
)*
} }
/// Returns whether no flags are set in `self`. /// Returns whether no flags are set in `self`.
#[inline] #[inline]
pub const fn is_empty(&self) -> bool { pub const fn is_empty(self) -> bool {
!( self.0 == 0
$(
self.$flag_name
)||+
)
} }
/// Returns whether any flags are set in both `self` and `other`. /// Returns whether any flags are set in both `self` and `other`.
#[inline] #[inline]
pub const fn intersects(&self, other: &Self) -> bool { pub const fn intersects(self, #[allow(unused_variables)] other: Self) -> bool {
$( self.0 & other.0 != 0
(self.$flag_name && other.$flag_name)
)||+
} }
/// Returns whether all flags in `other` are set in `self`. /// Returns whether all flags in `other` are set in `self`.
#[inline] #[inline]
pub const fn contains(&self, other: &Self) -> bool { pub const fn contains(self, #[allow(unused_variables)] other: Self) -> bool {
$( self.0 & other.0 == other.0
(self.$flag_name || !other.$flag_name)
)&&+
} }
/// Returns the union of `self` and `other`. /// Returns the union of `self` and `other`.
#[inline] #[inline]
pub const fn union(&self, other: &Self) -> Self { pub const fn union(self, #[allow(unused_variables)] other: Self) -> Self {
Self { Self(self.0 | other.0)
$(
$flag_name: (self.$flag_name || other.$flag_name),
)+
}
} }
/// Returns the intersection of `self` and `other`. /// Returns the intersection of `self` and `other`.
#[inline] #[inline]
pub const fn intersection(&self, other: &Self) -> Self { pub const fn intersection(self, #[allow(unused_variables)] other: Self) -> Self {
Self { Self(self.0 & other.0)
$(
$flag_name: (self.$flag_name && other.$flag_name),
)+
}
} }
/// Returns `self` without the flags set in `other`. /// Returns `self` without the flags set in `other`.
#[inline] #[inline]
pub const fn difference(&self, other: &Self) -> Self { pub const fn difference(self, #[allow(unused_variables)] other: Self) -> Self {
Self { Self(self.0 & !other.0)
$(
$flag_name: (self.$flag_name && !other.$flag_name),
)+
}
} }
/// Returns the flags set in `self` or `other`, but not both. /// Returns the flags that are set in `self` or `other`, but not in both.
#[inline] #[inline]
pub const fn symmetric_difference(&self, other: &Self) -> Self { pub const fn symmetric_difference(self, #[allow(unused_variables)] other: Self) -> Self {
Self { Self(self.0 ^ other.0)
$(
$flag_name: (self.$flag_name ^ other.$flag_name),
)+
}
} }
/// Returns the flags not in `self`. /// Returns the flags not in `self`.
#[inline] #[inline]
pub const fn complement(&self) -> Self { pub const fn complement(self) -> Self {
Self { Self(!self.0 & Self::all_raw())
$( }
$flag_name: !self.$flag_name,
)+ $( $($impls)* )?
}
impl Default for $ty {
#[inline]
fn default() -> Self {
Self::empty()
}
}
impl std::fmt::Debug for $ty {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
#[allow(unused_mut)]
let mut written = false;
$(
if self.intersects(Self::$flag_name) {
if written {
write!(f, " | ")?;
}
write!(f, stringify!($flag_name))?;
written = true;
}
)*
if !written {
write!(f, "empty()")?;
} }
Ok(())
} }
} }
impl From<$ty> for ash::vk::$ty_ffi { impl From<$ty> for ash::vk::$ty_ffi {
#[inline] #[inline]
fn from(val: $ty) -> Self { fn from(val: $ty) -> Self {
let mut result = ash::vk::$ty_ffi::empty(); ash::vk::$ty_ffi::from_raw(val.0)
$(
if val.$flag_name { result |= ash::vk::$ty_ffi::$flag_name_ffi }
)+
result
} }
} }
impl From<ash::vk::$ty_ffi> for $ty { impl From<ash::vk::$ty_ffi> for $ty {
#[inline] #[inline]
fn from(val: ash::vk::$ty_ffi) -> Self { fn from(val: ash::vk::$ty_ffi) -> Self {
Self { Self(val.as_raw() & Self::all_raw())
$(
$flag_name: val.intersects(ash::vk::$ty_ffi::$flag_name_ffi),
)+
}
}
}
impl Default for $ty {
#[inline]
fn default() -> Self {
Self {
$(
$flag_name: false,
)+
}
} }
} }
@ -169,14 +156,14 @@ macro_rules! vulkan_bitflags {
#[inline] #[inline]
fn bitand(self, rhs: Self) -> Self { fn bitand(self, rhs: Self) -> Self {
self.intersection(&rhs) self.intersection(rhs)
} }
} }
impl std::ops::BitAndAssign for $ty { impl std::ops::BitAndAssign for $ty {
#[inline] #[inline]
fn bitand_assign(&mut self, rhs: Self) { fn bitand_assign(&mut self, rhs: Self) {
*self = self.intersection(&rhs); *self = self.intersection(rhs);
} }
} }
@ -185,14 +172,14 @@ macro_rules! vulkan_bitflags {
#[inline] #[inline]
fn bitor(self, rhs: Self) -> Self { fn bitor(self, rhs: Self) -> Self {
self.union(&rhs) self.union(rhs)
} }
} }
impl std::ops::BitOrAssign for $ty { impl std::ops::BitOrAssign for $ty {
#[inline] #[inline]
fn bitor_assign(&mut self, rhs: Self) { fn bitor_assign(&mut self, rhs: Self) {
*self = self.union(&rhs); *self = self.union(rhs);
} }
} }
@ -201,14 +188,14 @@ macro_rules! vulkan_bitflags {
#[inline] #[inline]
fn bitxor(self, rhs: Self) -> Self { fn bitxor(self, rhs: Self) -> Self {
self.symmetric_difference(&rhs) self.symmetric_difference(rhs)
} }
} }
impl std::ops::BitXorAssign for $ty { impl std::ops::BitXorAssign for $ty {
#[inline] #[inline]
fn bitxor_assign(&mut self, rhs: Self) { fn bitxor_assign(&mut self, rhs: Self) {
*self = self.symmetric_difference(&rhs); *self = self.symmetric_difference(rhs);
} }
} }
@ -217,14 +204,14 @@ macro_rules! vulkan_bitflags {
#[inline] #[inline]
fn sub(self, rhs: Self) -> Self { fn sub(self, rhs: Self) -> Self {
self.difference(&rhs) self.difference(rhs)
} }
} }
impl std::ops::SubAssign for $ty { impl std::ops::SubAssign for $ty {
#[inline] #[inline]
fn sub_assign(&mut self, rhs: Self) { fn sub_assign(&mut self, rhs: Self) {
*self = self.difference(&rhs); *self = self.difference(rhs);
} }
} }
@ -239,9 +226,12 @@ macro_rules! vulkan_bitflags {
}; };
{ {
$(#[doc = $ty_doc:literal])*
#[non_exhaustive] #[non_exhaustive]
$ty:ident = $ty_ffi:ident($repr:ty);
$(#[doc = $ty_doc:literal])*
$ty:ident
$( impl { $($impls:item)* } )?
= $ty_ffi:ident($repr:ty);
$( $(
$(#[doc = $flag_doc:literal])* $(#[doc = $flag_doc:literal])*
@ -256,25 +246,19 @@ macro_rules! vulkan_bitflags {
)* )*
} => { } => {
$(#[doc = $ty_doc])* $(#[doc = $ty_doc])*
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct $ty { pub struct $ty($repr);
$(
$(#[doc = $flag_doc])*
pub $flag_name: bool,
)*
pub _ne: crate::NonExhaustive,
}
impl $ty { impl $ty {
$(
$(#[doc = $flag_doc])*
pub const $flag_name: Self = Self(ash::vk::$ty_ffi::$flag_name_ffi.as_raw());
)*
#[doc = concat!("Returns a `", stringify!($ty), "` with none of the flags set.")] #[doc = concat!("Returns a `", stringify!($ty), "` with none of the flags set.")]
#[inline] #[inline]
pub const fn empty() -> Self { pub const fn empty() -> Self {
Self { Self(0)
$(
$flag_name: false,
)*
_ne: crate::NonExhaustive(()),
}
} }
#[deprecated(since = "0.31.0", note = "Use `empty` instead.")] #[deprecated(since = "0.31.0", note = "Use `empty` instead.")]
@ -284,78 +268,59 @@ macro_rules! vulkan_bitflags {
Self::empty() Self::empty()
} }
const fn all_raw() -> $repr {
0
$(
| ash::vk::$ty_ffi::$flag_name_ffi.as_raw()
)*
}
/// Returns the number of flags set in self.
#[inline]
pub const fn count(self) -> u32 {
self.0.count_ones()
}
/// Returns whether no flags are set in `self`. /// Returns whether no flags are set in `self`.
#[inline] #[inline]
pub const fn is_empty(&self) -> bool { pub const fn is_empty(self) -> bool {
!( self.0 == 0
false
$(
|| self.$flag_name
)*
)
} }
/// Returns whether any flags are set in both `self` and `other`. /// Returns whether any flags are set in both `self` and `other`.
#[inline] #[inline]
pub const fn intersects(&self, #[allow(unused_variables)] other: &Self) -> bool { pub const fn intersects(self, #[allow(unused_variables)] other: Self) -> bool {
false self.0 & other.0 != 0
$(
|| (self.$flag_name && other.$flag_name)
)*
} }
/// Returns whether all flags in `other` are set in `self`. /// Returns whether all flags in `other` are set in `self`.
#[inline] #[inline]
pub const fn contains(&self, #[allow(unused_variables)] other: &Self) -> bool { pub const fn contains(self, #[allow(unused_variables)] other: Self) -> bool {
true self.0 & other.0 == other.0
$(
&& (self.$flag_name || !other.$flag_name)
)*
} }
/// Returns the union of `self` and `other`. /// Returns the union of `self` and `other`.
#[inline] #[inline]
pub const fn union(&self, #[allow(unused_variables)] other: &Self) -> Self { pub const fn union(self, #[allow(unused_variables)] other: Self) -> Self {
Self { Self(self.0 | other.0)
$(
$flag_name: (self.$flag_name || other.$flag_name),
)*
_ne: crate::NonExhaustive(()),
}
} }
/// Returns the intersection of `self` and `other`. /// Returns the intersection of `self` and `other`.
#[inline] #[inline]
pub const fn intersection(&self, #[allow(unused_variables)] other: &Self) -> Self { pub const fn intersection(self, #[allow(unused_variables)] other: Self) -> Self {
Self { Self(self.0 & other.0)
$(
$flag_name: (self.$flag_name && other.$flag_name),
)*
_ne: crate::NonExhaustive(()),
}
} }
/// Returns `self` without the flags set in `other`. /// Returns `self` without the flags set in `other`.
#[inline] #[inline]
pub const fn difference(&self, #[allow(unused_variables)] other: &Self) -> Self { pub const fn difference(self, #[allow(unused_variables)] other: Self) -> Self {
Self { Self(self.0 & !other.0)
$(
$flag_name: (self.$flag_name ^ other.$flag_name),
)*
_ne: crate::NonExhaustive(()),
}
} }
/// Returns the flags set in `self` or `other`, but not both. /// Returns the flags that are set in `self` or `other`, but not in both.
#[inline] #[inline]
pub const fn symmetric_difference(&self, #[allow(unused_variables)] other: &Self) -> Self { pub const fn symmetric_difference(self, #[allow(unused_variables)] other: Self) -> Self {
Self { Self(self.0 ^ other.0)
$(
$flag_name: (self.$flag_name ^ other.$flag_name),
)*
_ne: crate::NonExhaustive(()),
}
} }
#[allow(dead_code)] #[allow(dead_code)]
@ -365,7 +330,7 @@ macro_rules! vulkan_bitflags {
) -> Result<(), crate::RequirementNotMet> { ) -> Result<(), crate::RequirementNotMet> {
$( $(
$( $(
if self.$flag_name && ![ if self.intersects(Self::$flag_name) && ![
$( $(
device.api_version() >= crate::Version::$api_version, device.api_version() >= crate::Version::$api_version,
)? )?
@ -403,7 +368,7 @@ macro_rules! vulkan_bitflags {
) -> Result<(), crate::RequirementNotMet> { ) -> Result<(), crate::RequirementNotMet> {
$( $(
$( $(
if self.$flag_name && ![ if self.intersects(Self::$flag_name) && ![
$( $(
physical_device.api_version() >= crate::Version::$api_version, physical_device.api_version() >= crate::Version::$api_version,
)? )?
@ -441,7 +406,7 @@ macro_rules! vulkan_bitflags {
) -> Result<(), crate::RequirementNotMet> { ) -> Result<(), crate::RequirementNotMet> {
$( $(
$( $(
if self.$flag_name && ![ if self.intersects(Self::$flag_name) && ![
$( $(
instance.api_version() >= crate::Version::$api_version, instance.api_version() >= crate::Version::$api_version,
)? )?
@ -463,41 +428,52 @@ macro_rules! vulkan_bitflags {
Ok(()) Ok(())
} }
}
impl From<$ty> for ash::vk::$ty_ffi { $( $($impls)* )?
#[inline]
fn from(#[allow(unused_variables)] val: $ty) -> Self {
#[allow(unused_mut)]
let mut result = ash::vk::$ty_ffi::empty();
$(
if val.$flag_name { result |= ash::vk::$ty_ffi::$flag_name_ffi }
)*
result
}
}
impl From<ash::vk::$ty_ffi> for $ty {
#[inline]
fn from(#[allow(unused_variables)] val: ash::vk::$ty_ffi) -> Self {
Self {
$(
$flag_name: val.intersects(ash::vk::$ty_ffi::$flag_name_ffi),
)*
_ne: crate::NonExhaustive(()),
}
}
} }
impl Default for $ty { impl Default for $ty {
#[inline] #[inline]
fn default() -> Self { fn default() -> Self {
Self { Self::empty()
$( }
$flag_name: false, }
)*
_ne: crate::NonExhaustive(()), impl std::fmt::Debug for $ty {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
#[allow(unused_mut)]
let mut written = false;
$(
if self.intersects(Self::$flag_name) {
if written {
write!(f, " | ")?;
}
write!(f, stringify!($flag_name))?;
written = true;
}
)*
if !written {
write!(f, "empty()")?;
} }
Ok(())
}
}
impl From<$ty> for ash::vk::$ty_ffi {
#[inline]
fn from(val: $ty) -> Self {
ash::vk::$ty_ffi::from_raw(val.0)
}
}
impl From<ash::vk::$ty_ffi> for $ty {
#[inline]
fn from(val: ash::vk::$ty_ffi) -> Self {
Self(val.as_raw() & Self::all_raw())
} }
} }
@ -506,14 +482,14 @@ macro_rules! vulkan_bitflags {
#[inline] #[inline]
fn bitand(self, rhs: Self) -> Self { fn bitand(self, rhs: Self) -> Self {
self.intersection(&rhs) self.intersection(rhs)
} }
} }
impl std::ops::BitAndAssign for $ty { impl std::ops::BitAndAssign for $ty {
#[inline] #[inline]
fn bitand_assign(&mut self, rhs: Self) { fn bitand_assign(&mut self, rhs: Self) {
*self = self.intersection(&rhs); *self = self.intersection(rhs);
} }
} }
@ -522,14 +498,14 @@ macro_rules! vulkan_bitflags {
#[inline] #[inline]
fn bitor(self, rhs: Self) -> Self { fn bitor(self, rhs: Self) -> Self {
self.union(&rhs) self.union(rhs)
} }
} }
impl std::ops::BitOrAssign for $ty { impl std::ops::BitOrAssign for $ty {
#[inline] #[inline]
fn bitor_assign(&mut self, rhs: Self) { fn bitor_assign(&mut self, rhs: Self) {
*self = self.union(&rhs); *self = self.union(rhs);
} }
} }
@ -538,14 +514,14 @@ macro_rules! vulkan_bitflags {
#[inline] #[inline]
fn bitxor(self, rhs: Self) -> Self { fn bitxor(self, rhs: Self) -> Self {
self.symmetric_difference(&rhs) self.symmetric_difference(rhs)
} }
} }
impl std::ops::BitXorAssign for $ty { impl std::ops::BitXorAssign for $ty {
#[inline] #[inline]
fn bitxor_assign(&mut self, rhs: Self) { fn bitxor_assign(&mut self, rhs: Self) {
*self = self.symmetric_difference(&rhs); *self = self.symmetric_difference(rhs);
} }
} }
@ -554,14 +530,14 @@ macro_rules! vulkan_bitflags {
#[inline] #[inline]
fn sub(self, rhs: Self) -> Self { fn sub(self, rhs: Self) -> Self {
self.difference(&rhs) self.difference(rhs)
} }
} }
impl std::ops::SubAssign for $ty { impl std::ops::SubAssign for $ty {
#[inline] #[inline]
fn sub_assign(&mut self, rhs: Self) { fn sub_assign(&mut self, rhs: Self) {
*self = self.difference(&rhs); *self = self.difference(rhs);
} }
} }
}; };
@ -570,7 +546,9 @@ macro_rules! vulkan_bitflags {
macro_rules! vulkan_enum { macro_rules! vulkan_enum {
{ {
$(#[doc = $ty_doc:literal])* $(#[doc = $ty_doc:literal])*
$ty:ident = $ty_ffi:ident($repr:ty); $ty:ident
$( impl { $($impls:item)* } )?
= $ty_ffi:ident($repr:ty);
$( $(
$(#[doc = $flag_doc:literal])* $(#[doc = $flag_doc:literal])*
@ -587,6 +565,12 @@ macro_rules! vulkan_enum {
)+ )+
} }
$(
impl $ty {
$($impls)*
}
)?
impl From<$ty> for ash::vk::$ty_ffi { impl From<$ty> for ash::vk::$ty_ffi {
#[inline] #[inline]
fn from(val: $ty) -> Self { fn from(val: $ty) -> Self {
@ -610,9 +594,12 @@ macro_rules! vulkan_enum {
}; };
{ {
$(#[doc = $ty_doc:literal])*
#[non_exhaustive] #[non_exhaustive]
$ty:ident = $ty_ffi:ident($repr:ty);
$(#[doc = $ty_doc:literal])*
$ty:ident
$( impl { $($impls:item)* } )?
= $ty_ffi:ident($repr:ty);
$( $(
$(#[doc = $flag_doc:literal])* $(#[doc = $flag_doc:literal])*
@ -758,6 +745,10 @@ macro_rules! vulkan_enum {
Ok(()) Ok(())
} }
$(
$($impls)*
)?
} }
impl From<$ty> for ash::vk::$ty_ffi { impl From<$ty> for ash::vk::$ty_ffi {
@ -783,4 +774,118 @@ macro_rules! vulkan_enum {
}; };
} }
pub(crate) use {vulkan_bitflags, vulkan_enum}; macro_rules! vulkan_bitflags_enum {
{
#[non_exhaustive]
$(#[doc = $ty_bitflags_doc:literal])*
$ty_bitflags:ident
$( impl { $($impls_bitflags:item)* } )?
,
$(#[doc = $ty_enum_doc:literal])*
$ty_enum:ident
$( impl { $($impls_enum:item)* } )?
,
= $ty_ffi:ident($repr:ty);
$(
$(#[doc = $flag_doc:literal])*
$flag_name_bitflags:ident, $flag_name_enum:ident = $flag_name_ffi:ident
$({
$(api_version: $api_version:ident,)?
$(features: [$($feature:ident),+ $(,)?],)?
$(device_extensions: [$($device_extension:ident),+ $(,)?],)?
$(instance_extensions: [$($instance_extension:ident),+ $(,)?],)?
})?
,
)*
} => {
crate::macros::vulkan_bitflags! {
#[non_exhaustive]
$(#[doc = $ty_bitflags_doc])*
$ty_bitflags
impl {
/// Returns whether `self` contains the flag corresponding to `val`.
#[inline]
pub fn contains_enum(self, val: $ty_enum) -> bool {
self.intersects(val.into())
}
$( $($impls_bitflags)* )?
}
= $ty_ffi($repr);
$(
$(#[doc = $flag_doc])*
$flag_name_bitflags = $flag_name_ffi
$({
$(api_version: $api_version,)?
$(features: [$($feature),+],)?
$(device_extensions: [$($device_extension),+],)?
$(instance_extensions: [$($instance_extension),+],)?
})?
,
)*
}
crate::macros::vulkan_enum! {
#[non_exhaustive]
$(#[doc = $ty_enum_doc])*
$ty_enum
$( impl { $($impls_enum)* } )?
= $ty_ffi($repr);
$(
$(#[doc = $flag_doc])*
$flag_name_enum = $flag_name_ffi
$({
$(api_version: $api_version,)?
$(features: [$($feature),+],)?
$(device_extensions: [$($device_extension),+],)?
$(instance_extensions: [$($instance_extension),+],)?
})?
,
)*
}
impl From<$ty_enum> for $ty_bitflags {
#[inline]
fn from(val: $ty_enum) -> Self {
Self(val as $repr)
}
}
impl FromIterator<$ty_enum> for $ty_bitflags {
#[inline]
fn from_iter<T>(iter: T) -> Self where T: IntoIterator<Item = $ty_enum> {
iter.into_iter().map(|item| Self::from(item)).fold(Self::empty(), |r, i| r.union(i))
}
}
impl IntoIterator for $ty_bitflags {
type Item = $ty_enum;
type IntoIter = std::iter::Flatten<
std::array::IntoIter<
Option<Self::Item>,
{ $ty_bitflags::all_raw().count_ones() as usize },
>
>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
[
$(
self.intersects(Self::$flag_name_bitflags)
.then_some($ty_enum::$flag_name_enum),
)*
].into_iter().flatten()
}
}
}
}
pub(crate) use {vulkan_bitflags, vulkan_bitflags_enum, vulkan_enum};

View File

@ -353,17 +353,17 @@ impl From<MemoryUsage> for MemoryTypeFilter {
match usage { match usage {
MemoryUsage::GpuOnly => { MemoryUsage::GpuOnly => {
filter.preferred_flags.device_local = true; filter.preferred_flags |= MemoryPropertyFlags::DEVICE_LOCAL;
filter.not_preferred_flags.host_visible = true; filter.not_preferred_flags |= MemoryPropertyFlags::HOST_VISIBLE;
} }
MemoryUsage::Upload => { MemoryUsage::Upload => {
filter.required_flags.host_visible = true; filter.required_flags |= MemoryPropertyFlags::HOST_VISIBLE;
filter.preferred_flags.device_local = true; filter.preferred_flags |= MemoryPropertyFlags::DEVICE_LOCAL;
filter.not_preferred_flags.host_cached = true; filter.not_preferred_flags |= MemoryPropertyFlags::HOST_CACHED;
} }
MemoryUsage::Download => { MemoryUsage::Download => {
filter.required_flags.host_visible = true; filter.required_flags |= MemoryPropertyFlags::HOST_VISIBLE;
filter.preferred_flags.host_cached = true; filter.preferred_flags |= MemoryPropertyFlags::HOST_CACHED;
} }
} }
@ -464,8 +464,8 @@ impl Default for AllocationCreateInfo<'_> {
pub enum MemoryUsage { pub enum MemoryUsage {
/// The memory is intended to only be used by the GPU. /// The memory is intended to only be used by the GPU.
/// ///
/// Prefers picking a memory type with the [`device_local`] flag and without the /// Prefers picking a memory type with the [`DEVICE_LOCAL`] flag and
/// [`host_visible`] flag. /// without the [`HOST_VISIBLE`] flag.
/// ///
/// This option is what you will always want to use unless the memory needs to be accessed by /// This option is what you will always want to use unless the memory needs to be accessed by
/// the CPU, because a memory type that can only be accessed by the GPU is going to give the /// the CPU, because a memory type that can only be accessed by the GPU is going to give the
@ -473,37 +473,37 @@ pub enum MemoryUsage {
/// once and then never again, or resources that are only written and read by the GPU, like /// once and then never again, or resources that are only written and read by the GPU, like
/// render targets and intermediary buffers. /// render targets and intermediary buffers.
/// ///
/// [`device_local`]: MemoryPropertyFlags::device_local /// [`DEVICE_LOCAL`]: MemoryPropertyFlags::DEVICE_LOCAL
/// [`host_visible`]: MemoryPropertyFlags::host_visible /// [`HOST_VISIBLE`]: MemoryPropertyFlags::HOST_VISIBLE
GpuOnly, GpuOnly,
/// The memory is intended for upload to the GPU. /// The memory is intended for upload to the GPU.
/// ///
/// Guarantees picking a memory type with the [`host_visible`] flag. Prefers picking one /// Guarantees picking a memory type with the [`HOST_VISIBLE`] flag. Prefers picking one
/// without the [`host_cached`] flag and with the [`device_local`] flag. /// without the [`HOST_CACHED`] flag and with the [`DEVICE_LOCAL`] flag.
/// ///
/// This option is best suited for resources that need to be constantly updated by the CPU, /// This option is best suited for resources that need to be constantly updated by the CPU,
/// like vertex and index buffers for example. It is also neccessary for *staging buffers*, /// like vertex and index buffers for example. It is also neccessary for *staging buffers*,
/// whose only purpose in life it is to get data into `device_local` memory or texels into an /// whose only purpose in life it is to get data into `device_local` memory or texels into an
/// optimal image. /// optimal image.
/// ///
/// [`host_visible`]: MemoryPropertyFlags::host_visible /// [`HOST_VISIBLE`]: MemoryPropertyFlags::HOST_VISIBLE
/// [`host_cached`]: MemoryPropertyFlags::host_cached /// [`HOST_CACHED`]: MemoryPropertyFlags::HOST_CACHED
/// [`device_local`]: MemoryPropertyFlags::device_local /// [`DEVICE_LOCAL`]: MemoryPropertyFlags::DEVICE_LOCAL
Upload, Upload,
/// The memory is intended for download from the GPU. /// The memory is intended for download from the GPU.
/// ///
/// Guarantees picking a memory type with the [`host_visible`] flag. Prefers picking one with /// Guarantees picking a memory type with the [`HOST_VISIBLE`] flag. Prefers picking one with
/// the [`host_cached`] flag and without the [`device_local`] flag. /// the [`HOST_CACHED`] flag and without the [`DEVICE_LOCAL`] flag.
/// ///
/// This option is best suited if you're using the GPU for things other than rendering and you /// This option is best suited if you're using the GPU for things other than rendering and you
/// need to get the results back to the CPU. That might be compute shading, or image or video /// need to get the results back to the CPU. That might be compute shading, or image or video
/// manipulation, or screenshotting for example. /// manipulation, or screenshotting for example.
/// ///
/// [`host_visible`]: MemoryPropertyFlags::host_visible /// [`HOST_VISIBLE`]: MemoryPropertyFlags::HOST_VISIBLE
/// [`host_cached`]: MemoryPropertyFlags::host_cached /// [`HOST_CACHED`]: MemoryPropertyFlags::HOST_CACHED
/// [`device_local`]: MemoryPropertyFlags::device_local /// [`DEVICE_LOCAL`]: MemoryPropertyFlags::DEVICE_LOCAL
Download, Download,
} }
@ -762,7 +762,7 @@ impl<S: Suballocator> GenericMemoryAllocator<S> {
&& device.enabled_extensions().khr_external_memory) && device.enabled_extensions().khr_external_memory)
{ {
return Err(GenericMemoryAllocatorCreationError::RequirementNotMet { return Err(GenericMemoryAllocatorCreationError::RequirementNotMet {
required_for: "`create_info.export_handle_types` was not empty", required_for: "`create_info.export_handle_types` is not empty",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
api_version: Some(Version::V1_1), api_version: Some(Version::V1_1),
device_extensions: &["khr_external_memory"], device_extensions: &["khr_external_memory"],
@ -853,12 +853,13 @@ impl<S: Suballocator> GenericMemoryAllocator<S> {
let mut memory_type_bits = u32::MAX; let mut memory_type_bits = u32::MAX;
for (index, MemoryType { property_flags, .. }) in memory_types.iter().enumerate() { for (index, MemoryType { property_flags, .. }) in memory_types.iter().enumerate() {
if property_flags.lazily_allocated if property_flags.intersects(
|| property_flags.protected MemoryPropertyFlags::LAZILY_ALLOCATED
|| property_flags.device_coherent | MemoryPropertyFlags::PROTECTED
|| property_flags.device_uncached | MemoryPropertyFlags::DEVICE_COHERENT
|| property_flags.rdma_capable | MemoryPropertyFlags::DEVICE_UNCACHED
{ | MemoryPropertyFlags::RDMA_CAPABLE,
) {
// VUID-VkMemoryAllocateInfo-memoryTypeIndex-01872 // VUID-VkMemoryAllocateInfo-memoryTypeIndex-01872
// VUID-vkAllocateMemory-deviceCoherentMemory-02790 // VUID-vkAllocateMemory-deviceCoherentMemory-02790
// Lazily allocated memory would just cause problems for suballocation in general. // Lazily allocated memory would just cause problems for suballocation in general.
@ -879,9 +880,10 @@ impl<S: Suballocator> GenericMemoryAllocator<S> {
allocation_type, allocation_type,
dedicated_allocation, dedicated_allocation,
export_handle_types, export_handle_types,
flags: MemoryAllocateFlags { flags: if device_address {
device_address, MemoryAllocateFlags::DEVICE_ADDRESS
..Default::default() } else {
MemoryAllocateFlags::empty()
}, },
memory_type_bits, memory_type_bits,
max_allocations, max_allocations,
@ -994,9 +996,9 @@ unsafe impl<S: Suballocator> MemoryAllocator for GenericMemoryAllocator<S> {
/// # Panics /// # Panics
/// ///
/// - Panics if `memory_type_index` is not less than the number of available memory types. /// - Panics if `memory_type_index` is not less than the number of available memory types.
/// - Panics if `memory_type_index` refers to a memory type which has the [`protected`] flag set /// - Panics if `memory_type_index` refers to a memory type which has the [`PROTECTED`] flag set
/// and the [`protected_memory`] feature is not enabled on the device. /// and the [`protected_memory`] feature is not enabled on the device.
/// - Panics if `memory_type_index` refers to a memory type which has the [`device_coherent`] /// - Panics if `memory_type_index` refers to a memory type which has the [`DEVICE_COHERENT`]
/// flag set and the [`device_coherent_memory`] feature is not enabled on the device. /// flag set and the [`device_coherent_memory`] feature is not enabled on the device.
/// - Panics if `create_info.size` is zero. /// - Panics if `create_info.size` is zero.
/// - Panics if `create_info.alignment` is zero. /// - Panics if `create_info.alignment` is zero.
@ -1012,9 +1014,9 @@ unsafe impl<S: Suballocator> MemoryAllocator for GenericMemoryAllocator<S> {
/// - Returns [`SuballocatorBlockSizeExceeded`] if `S` is `PoolAllocator<BLOCK_SIZE>` and /// - Returns [`SuballocatorBlockSizeExceeded`] if `S` is `PoolAllocator<BLOCK_SIZE>` and
/// `create_info.size` is greater than `BLOCK_SIZE`. /// `create_info.size` is greater than `BLOCK_SIZE`.
/// ///
/// [`protected`]: MemoryPropertyFlags::protected /// [`PROTECTED`]: MemoryPropertyFlags::PROTECTED
/// [`protected_memory`]: crate::device::Features::protected_memory /// [`protected_memory`]: crate::device::Features::protected_memory
/// [`device_coherent`]: MemoryPropertyFlags::device_coherent /// [`DEVICE_COHERENT`]: MemoryPropertyFlags::DEVICE_COHERENT
/// [`device_coherent_memory`]: crate::device::Features::device_coherent_memory /// [`device_coherent_memory`]: crate::device::Features::device_coherent_memory
/// [`TooManyObjects`]: VulkanError::TooManyObjects /// [`TooManyObjects`]: VulkanError::TooManyObjects
/// [`BlockSizeExceeded`]: AllocationCreationError::BlockSizeExceeded /// [`BlockSizeExceeded`]: AllocationCreationError::BlockSizeExceeded
@ -1235,13 +1237,11 @@ unsafe impl<S: Suballocator> MemoryAllocator for GenericMemoryAllocator<S> {
/// `create_info.size` is greater than `BLOCK_SIZE` and a dedicated allocation was not /// `create_info.size` is greater than `BLOCK_SIZE` and a dedicated allocation was not
/// created. /// created.
/// ///
/// [`device_local`]: MemoryPropertyFlags::device_local
/// [`host_visible`]: MemoryPropertyFlags::host_visible
/// [`TooManyObjects`]: VulkanError::TooManyObjects /// [`TooManyObjects`]: VulkanError::TooManyObjects
/// [`SuballocatorBlockSizeExceeded`]: AllocationCreationError::SuballocatorBlockSizeExceeded
/// [`OutOfPoolMemory`]: AllocationCreationError::OutOfPoolMemory /// [`OutOfPoolMemory`]: AllocationCreationError::OutOfPoolMemory
/// [`DedicatedAllocationRequired`]: AllocationCreationError::DedicatedAllocationRequired /// [`DedicatedAllocationRequired`]: AllocationCreationError::DedicatedAllocationRequired
/// [`BlockSizeExceeded`]: AllocationCreationError::BlockSizeExceeded /// [`BlockSizeExceeded`]: AllocationCreationError::BlockSizeExceeded
/// [`SuballocatorBlockSizeExceeded`]: AllocationCreationError::SuballocatorBlockSizeExceeded
fn allocate( fn allocate(
&self, &self,
create_info: AllocationCreateInfo<'_>, create_info: AllocationCreateInfo<'_>,
@ -1549,10 +1549,10 @@ pub struct GenericMemoryAllocatorCreateInfo<'b, 'e> {
pub export_handle_types: &'e [ExternalMemoryHandleTypes], pub export_handle_types: &'e [ExternalMemoryHandleTypes],
/// Whether the allocator should allocate the [`DeviceMemory`] blocks with the /// Whether the allocator should allocate the [`DeviceMemory`] blocks with the
/// [`device_address`] flag set. /// [`DEVICE_ADDRESS`] flag set.
/// ///
/// This is required if you want to allocate memory for buffers that have the /// This is required if you want to allocate memory for buffers that have the
/// [`shader_device_address`] usage set. For this option too, there is no reason to disable it. /// [`SHADER_DEVICE_ADDRESS`] usage set. For this option too, there is no reason to disable it.
/// ///
/// This option is silently ignored (treated as `false`) if the [`buffer_device_address`] /// This option is silently ignored (treated as `false`) if the [`buffer_device_address`]
/// feature is not enabled on the device or if the [`ext_buffer_device_address`] extension is /// feature is not enabled on the device or if the [`ext_buffer_device_address`] extension is
@ -1561,8 +1561,8 @@ pub struct GenericMemoryAllocatorCreateInfo<'b, 'e> {
/// ///
/// The default value is `true`. /// The default value is `true`.
/// ///
/// [`device_address`]: MemoryAllocateFlags::device_address /// [`DEVICE_ADDRESS`]: MemoryAllocateFlags::DEVICE_ADDRESS
/// [`shader_device_address`]: crate::buffer::BufferUsage::shader_device_address /// [`SHADER_DEVICE_ADDRESS`]: crate::buffer::BufferUsage::SHADER_DEVICE_ADDRESS
/// [`buffer_device_address`]: crate::device::Features::buffer_device_address /// [`buffer_device_address`]: crate::device::Features::buffer_device_address
/// [`ext_buffer_device_address`]: crate::device::DeviceExtensions::ext_buffer_device_address /// [`ext_buffer_device_address`]: crate::device::DeviceExtensions::ext_buffer_device_address
/// [`khr_device_group`]: crate::device::DeviceExtensions::khr_device_group /// [`khr_device_group`]: crate::device::DeviceExtensions::khr_device_group

View File

@ -18,7 +18,7 @@ use super::{array_vec::ArrayVec, AllocationCreateInfo, AllocationCreationError};
use crate::{ use crate::{
device::{Device, DeviceOwned}, device::{Device, DeviceOwned},
image::ImageTiling, image::ImageTiling,
memory::DeviceMemory, memory::{DeviceMemory, MemoryPropertyFlags},
DeviceSize, OomError, VulkanError, VulkanObject, DeviceSize, OomError, VulkanError, VulkanObject,
}; };
use crossbeam_queue::ArrayQueue; use crossbeam_queue::ArrayQueue;
@ -102,7 +102,7 @@ impl MemoryAlloc {
[memory_type_index as usize] [memory_type_index as usize]
.property_flags; .property_flags;
let mapped_ptr = if property_flags.host_visible { let mapped_ptr = if property_flags.intersects(MemoryPropertyFlags::HOST_VISIBLE) {
let fns = device.fns(); let fns = device.fns();
let mut output = MaybeUninit::uninit(); let mut output = MaybeUninit::uninit();
// This is always valid because we are mapping the whole range. // This is always valid because we are mapping the whole range.
@ -124,9 +124,10 @@ impl MemoryAlloc {
None None
}; };
let atom_size = (property_flags.host_visible && !property_flags.host_coherent) let atom_size = (property_flags.intersects(MemoryPropertyFlags::HOST_VISIBLE)
.then_some(physical_device.properties().non_coherent_atom_size) && !property_flags.intersects(MemoryPropertyFlags::HOST_COHERENT))
.and_then(NonZeroU64::new); .then_some(physical_device.properties().non_coherent_atom_size)
.and_then(NonZeroU64::new);
Ok(MemoryAlloc { Ok(MemoryAlloc {
offset: 0, offset: 0,
@ -225,7 +226,7 @@ impl MemoryAlloc {
/// - Panics if `range.end` exceeds `self.size`. /// - Panics if `range.end` exceeds `self.size`.
/// - Panics if `range.start` or `range.end` are not a multiple of the `non_coherent_atom_size`. /// - Panics if `range.start` or `range.end` are not a multiple of the `non_coherent_atom_size`.
/// ///
/// [host-coherent]: super::MemoryPropertyFlags::host_coherent /// [host-coherent]: crate::memory::MemoryPropertyFlags::HOST_COHERENT
/// [`non_coherent_atom_size`]: crate::device::Properties::non_coherent_atom_size /// [`non_coherent_atom_size`]: crate::device::Properties::non_coherent_atom_size
#[inline] #[inline]
pub unsafe fn invalidate_range(&self, range: Range<DeviceSize>) -> Result<(), OomError> { pub unsafe fn invalidate_range(&self, range: Range<DeviceSize>) -> Result<(), OomError> {
@ -266,7 +267,7 @@ impl MemoryAlloc {
/// - Panics if `range.end` exceeds `self.size`. /// - Panics if `range.end` exceeds `self.size`.
/// - Panics if `range.start` or `range.end` are not a multiple of the `non_coherent_atom_size`. /// - Panics if `range.start` or `range.end` are not a multiple of the `non_coherent_atom_size`.
/// ///
/// [host-coherent]: super::MemoryPropertyFlags::host_coherent /// [host-coherent]: crate::memory::MemoryPropertyFlags::HOST_COHERENT
/// [`non_coherent_atom_size`]: crate::device::Properties::non_coherent_atom_size /// [`non_coherent_atom_size`]: crate::device::Properties::non_coherent_atom_size
#[inline] #[inline]
pub unsafe fn flush_range(&self, range: Range<DeviceSize>) -> Result<(), OomError> { pub unsafe fn flush_range(&self, range: Range<DeviceSize>) -> Result<(), OomError> {
@ -605,7 +606,7 @@ unsafe impl DeviceOwned for MemoryAlloc {
/// Allocating a region to suballocatate: /// Allocating a region to suballocatate:
/// ///
/// ``` /// ```
/// use vulkano::memory::{DeviceMemory, MemoryAllocateInfo, MemoryType}; /// use vulkano::memory::{DeviceMemory, MemoryAllocateInfo, MemoryPropertyFlags, MemoryType};
/// use vulkano::memory::allocator::MemoryAlloc; /// use vulkano::memory::allocator::MemoryAlloc;
/// # let device: std::sync::Arc<vulkano::device::Device> = return; /// # let device: std::sync::Arc<vulkano::device::Device> = return;
/// ///
@ -620,7 +621,7 @@ unsafe impl DeviceOwned for MemoryAlloc {
/// // requirements, instead of picking the first one that satisfies them. Also, you have to /// // requirements, instead of picking the first one that satisfies them. Also, you have to
/// // take the requirements of the resources you want to allocate memory for into consideration. /// // take the requirements of the resources you want to allocate memory for into consideration.
/// .find_map(|(index, MemoryType { property_flags, .. })| { /// .find_map(|(index, MemoryType { property_flags, .. })| {
/// property_flags.device_local.then_some(index) /// property_flags.intersects(MemoryPropertyFlags::DEVICE_LOCAL).then_some(index)
/// }) /// })
/// .unwrap() as u32; /// .unwrap() as u32;
/// ///

View File

@ -10,7 +10,8 @@
use super::{DedicatedAllocation, DedicatedTo}; use super::{DedicatedAllocation, DedicatedTo};
use crate::{ use crate::{
device::{Device, DeviceOwned}, device::{Device, DeviceOwned},
macros::{vulkan_bitflags, vulkan_enum}, macros::{vulkan_bitflags, vulkan_bitflags_enum},
memory::MemoryPropertyFlags,
DeviceSize, OomError, RequirementNotMet, RequiresOneOf, Version, VulkanError, VulkanObject, DeviceSize, OomError, RequirementNotMet, RequiresOneOf, Version, VulkanError, VulkanObject,
}; };
use std::{ use std::{
@ -173,10 +174,14 @@ impl DeviceMemory {
})?; })?;
// VUID-VkMemoryAllocateInfo-memoryTypeIndex-01872 // VUID-VkMemoryAllocateInfo-memoryTypeIndex-01872
if memory_type.property_flags.protected && !device.enabled_features().protected_memory { if memory_type
.property_flags
.intersects(MemoryPropertyFlags::PROTECTED)
&& !device.enabled_features().protected_memory
{
return Err(DeviceMemoryError::RequirementNotMet { return Err(DeviceMemoryError::RequirementNotMet {
required_for: "`allocate_info.memory_type_index` refers to a memory type where \ required_for: "`allocate_info.memory_type_index` refers to a memory type where \
`property_flags.protected` is set", `property_flags` contains `MemoryPropertyFlags::PROTECTED`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["protected_memory"], features: &["protected_memory"],
..Default::default() ..Default::default()
@ -197,12 +202,14 @@ impl DeviceMemory {
} }
// VUID-vkAllocateMemory-deviceCoherentMemory-02790 // VUID-vkAllocateMemory-deviceCoherentMemory-02790
if memory_type.property_flags.device_coherent if memory_type
.property_flags
.intersects(MemoryPropertyFlags::DEVICE_COHERENT)
&& !device.enabled_features().device_coherent_memory && !device.enabled_features().device_coherent_memory
{ {
return Err(DeviceMemoryError::RequirementNotMet { return Err(DeviceMemoryError::RequirementNotMet {
required_for: "`allocate_info.memory_type_index` refers to a memory type where \ required_for: "`allocate_info.memory_type_index` refers to a memory type where \
`property_flags.device_coherent` is set", `property_flags` contains `MemoryPropertyFlags::DEVICE_COHERENT`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["device_coherent_memory"], features: &["device_coherent_memory"],
..Default::default() ..Default::default()
@ -278,8 +285,8 @@ impl DeviceMemory {
} => { } => {
if !device.enabled_extensions().khr_external_memory_fd { if !device.enabled_extensions().khr_external_memory_fd {
return Err(DeviceMemoryError::RequirementNotMet { return Err(DeviceMemoryError::RequirementNotMet {
required_for: required_for: "`allocate_info.import_info` is \
"`allocate_info.import_info` is `Some(MemoryImportInfo::Fd)`", `Some(MemoryImportInfo::Fd)`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
device_extensions: &["khr_external_memory_fd"], device_extensions: &["khr_external_memory_fd"],
..Default::default() ..Default::default()
@ -330,8 +337,8 @@ impl DeviceMemory {
} => { } => {
if !device.enabled_extensions().khr_external_memory_win32 { if !device.enabled_extensions().khr_external_memory_win32 {
return Err(DeviceMemoryError::RequirementNotMet { return Err(DeviceMemoryError::RequirementNotMet {
required_for: required_for: "`allocate_info.import_info` is \
"`allocate_info.import_info` is `Some(MemoryImportInfo::Win32)`", `Some(MemoryImportInfo::Win32)`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
device_extensions: &["khr_external_memory_win32"], device_extensions: &["khr_external_memory_win32"],
..Default::default() ..Default::default()
@ -390,11 +397,12 @@ impl DeviceMemory {
}); });
} }
if flags.device_address { if flags.intersects(MemoryAllocateFlags::DEVICE_ADDRESS) {
// VUID-VkMemoryAllocateInfo-flags-03331 // VUID-VkMemoryAllocateInfo-flags-03331
if !device.enabled_features().buffer_device_address { if !device.enabled_features().buffer_device_address {
return Err(DeviceMemoryError::RequirementNotMet { return Err(DeviceMemoryError::RequirementNotMet {
required_for: "`allocate_info.flags.device_address` is `true`", required_for: "`allocate_info.flags` contains \
`MemoryAllocateFlags::DEVICE_ADDRESS`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["buffer_device_address"], features: &["buffer_device_address"],
..Default::default() ..Default::default()
@ -404,7 +412,8 @@ impl DeviceMemory {
if device.enabled_extensions().ext_buffer_device_address { if device.enabled_extensions().ext_buffer_device_address {
return Err(DeviceMemoryError::RequirementNotMet { return Err(DeviceMemoryError::RequirementNotMet {
required_for: "`allocate_info.flags.device_address` is `true`", required_for: "`allocate_info.flags` contains \
`MemoryAllocateFlags::DEVICE_ADDRESS`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
api_version: Some(Version::V1_2), api_version: Some(Version::V1_2),
device_extensions: &["khr_buffer_device_address"], device_extensions: &["khr_buffer_device_address"],
@ -609,8 +618,10 @@ impl DeviceMemory {
/// The device may change this value at any time, and the returned value may be /// The device may change this value at any time, and the returned value may be
/// already out-of-date. /// already out-of-date.
/// ///
/// `self` must have been allocated from a memory type that has the /// `self` must have been allocated from a memory type that has the [`LAZILY_ALLOCATED`] flag
/// [`lazily_allocated`](crate::memory::MemoryPropertyFlags::lazily_allocated) flag set. /// set.
///
/// [`LAZILY_ALLOCATED`]: crate::memory::MemoryPropertyFlags::LAZILY_ALLOCATED
#[inline] #[inline]
pub fn commitment(&self) -> Result<DeviceSize, DeviceMemoryError> { pub fn commitment(&self) -> Result<DeviceSize, DeviceMemoryError> {
self.validate_commitment()?; self.validate_commitment()?;
@ -626,7 +637,10 @@ impl DeviceMemory {
.memory_types[self.memory_type_index as usize]; .memory_types[self.memory_type_index as usize];
// VUID-vkGetDeviceMemoryCommitment-memory-00690 // VUID-vkGetDeviceMemoryCommitment-memory-00690
if !memory_type.property_flags.lazily_allocated { if !memory_type
.property_flags
.intersects(MemoryPropertyFlags::LAZILY_ALLOCATED)
{
return Err(DeviceMemoryError::NotLazilyAllocated); return Err(DeviceMemoryError::NotLazilyAllocated);
} }
@ -855,212 +869,87 @@ pub enum MemoryImportInfo {
}, },
} }
vulkan_enum! { vulkan_bitflags_enum! {
/// Describes a handle type used for Vulkan external memory apis. This is **not** just a
/// suggestion. Check out vkExternalMemoryHandleTypeFlagBits in the Vulkan spec.
///
/// If you specify an handle type that doesnt make sense (for example, using a dma-buf handle
/// type on Windows) when using this handle, a panic will happen.
#[non_exhaustive] #[non_exhaustive]
ExternalMemoryHandleType = ExternalMemoryHandleTypeFlags(u32);
// TODO: document /// A set of [`ExternalMemoryHandleType`] values.
OpaqueFd = OPAQUE_FD, ExternalMemoryHandleTypes,
// TODO: document /// A handle type used to export or import memory to/from an external source.
OpaqueWin32 = OPAQUE_WIN32, ExternalMemoryHandleType,
// TODO: document = ExternalMemoryHandleTypeFlags(u32);
OpaqueWin32Kmt = OPAQUE_WIN32_KMT,
// TODO: document /// A POSIX file descriptor handle that is only usable with Vulkan and compatible APIs.
D3D11Texture = D3D11_TEXTURE, OPAQUE_FD, OpaqueFd = OPAQUE_FD,
// TODO: document /// A Windows NT handle that is only usable with Vulkan and compatible APIs.
D3D11TextureKmt = D3D11_TEXTURE_KMT, OPAQUE_WIN32, OpaqueWin32 = OPAQUE_WIN32,
// TODO: document /// A Windows global share handle that is only usable with Vulkan and compatible APIs.
D3D12Heap = D3D12_HEAP, OPAQUE_WIN32_KMT, OpaqueWin32Kmt = OPAQUE_WIN32_KMT,
// TODO: document /// A Windows NT handle that refers to a Direct3D 10 or 11 texture resource.
D3D12Resource = D3D12_RESOURCE, D3D11_TEXTURE, D3D11Texture = D3D11_TEXTURE,
// TODO: document /// A Windows global share handle that refers to a Direct3D 10 or 11 texture resource.
DmaBuf = DMA_BUF_EXT { D3D11_TEXTURE_KMT, D3D11TextureKmt = D3D11_TEXTURE_KMT,
/// A Windows NT handle that refers to a Direct3D 12 heap resource.
D3D12_HEAP, D3D12Heap = D3D12_HEAP,
/// A Windows NT handle that refers to a Direct3D 12 committed resource.
D3D12_RESOURCE, D3D12Resource = D3D12_RESOURCE,
/// A POSIX file descriptor handle that refers to a Linux dma-buf.
DMA_BUF, DmaBuf = DMA_BUF_EXT {
device_extensions: [ext_external_memory_dma_buf], device_extensions: [ext_external_memory_dma_buf],
}, },
// TODO: document /// A handle for an Android `AHardwareBuffer` object.
AndroidHardwareBuffer = ANDROID_HARDWARE_BUFFER_ANDROID { ANDROID_HARDWARE_BUFFER, AndroidHardwareBuffer = ANDROID_HARDWARE_BUFFER_ANDROID {
device_extensions: [android_external_memory_android_hardware_buffer], device_extensions: [android_external_memory_android_hardware_buffer],
}, },
// TODO: document /// A pointer to memory that was allocated by the host.
HostAllocation = HOST_ALLOCATION_EXT { HOST_ALLOCATION, HostAllocation = HOST_ALLOCATION_EXT {
device_extensions: [ext_external_memory_host], device_extensions: [ext_external_memory_host],
}, },
// TODO: document /// A pointer to a memory mapping on the host that maps non-host memory.
HostMappedForeignMemory = HOST_MAPPED_FOREIGN_MEMORY_EXT { HOST_MAPPED_FOREIGN_MEMORY, HostMappedForeignMemory = HOST_MAPPED_FOREIGN_MEMORY_EXT {
device_extensions: [ext_external_memory_host], device_extensions: [ext_external_memory_host],
}, },
// TODO: document /// A Zircon handle to a virtual memory object.
ZirconVmo = ZIRCON_VMO_FUCHSIA { ZIRCON_VMO, ZirconVmo = ZIRCON_VMO_FUCHSIA {
device_extensions: [fuchsia_external_memory], device_extensions: [fuchsia_external_memory],
}, },
// TODO: document /// A Remote Direct Memory Address handle to an allocation that is accessible by remote devices.
RdmaAddress = RDMA_ADDRESS_NV { RDMA_ADDRESS, RdmaAddress = RDMA_ADDRESS_NV {
device_extensions: [nv_external_memory_rdma], device_extensions: [nv_external_memory_rdma],
}, },
} }
vulkan_bitflags! { vulkan_bitflags! {
/// A mask of multiple handle types.
#[non_exhaustive] #[non_exhaustive]
ExternalMemoryHandleTypes = ExternalMemoryHandleTypeFlags(u32);
// TODO: document
opaque_fd = OPAQUE_FD,
// TODO: document
opaque_win32 = OPAQUE_WIN32,
// TODO: document
opaque_win32_kmt = OPAQUE_WIN32_KMT,
// TODO: document
d3d11_texture = D3D11_TEXTURE,
// TODO: document
d3d11_texture_kmt = D3D11_TEXTURE_KMT,
// TODO: document
d3d12_heap = D3D12_HEAP,
// TODO: document
d3d12_resource = D3D12_RESOURCE,
// TODO: document
dma_buf = DMA_BUF_EXT {
device_extensions: [ext_external_memory_dma_buf],
},
// TODO: document
android_hardware_buffer = ANDROID_HARDWARE_BUFFER_ANDROID {
device_extensions: [android_external_memory_android_hardware_buffer],
},
// TODO: document
host_allocation = HOST_ALLOCATION_EXT {
device_extensions: [ext_external_memory_host],
},
// TODO: document
host_mapped_foreign_memory = HOST_MAPPED_FOREIGN_MEMORY_EXT {
device_extensions: [ext_external_memory_host],
},
// TODO: document
zircon_vmo = ZIRCON_VMO_FUCHSIA {
device_extensions: [fuchsia_external_memory],
},
// TODO: document
rdma_address = RDMA_ADDRESS_NV {
device_extensions: [nv_external_memory_rdma],
},
}
impl From<ExternalMemoryHandleType> for ExternalMemoryHandleTypes {
#[inline]
fn from(val: ExternalMemoryHandleType) -> Self {
let mut result = Self::empty();
match val {
ExternalMemoryHandleType::OpaqueFd => result.opaque_fd = true,
ExternalMemoryHandleType::OpaqueWin32 => result.opaque_win32 = true,
ExternalMemoryHandleType::OpaqueWin32Kmt => result.opaque_win32_kmt = true,
ExternalMemoryHandleType::D3D11Texture => result.d3d11_texture = true,
ExternalMemoryHandleType::D3D11TextureKmt => result.d3d11_texture_kmt = true,
ExternalMemoryHandleType::D3D12Heap => result.d3d12_heap = true,
ExternalMemoryHandleType::D3D12Resource => result.d3d12_resource = true,
ExternalMemoryHandleType::DmaBuf => result.dma_buf = true,
ExternalMemoryHandleType::AndroidHardwareBuffer => {
result.android_hardware_buffer = true
}
ExternalMemoryHandleType::HostAllocation => result.host_allocation = true,
ExternalMemoryHandleType::HostMappedForeignMemory => {
result.host_mapped_foreign_memory = true
}
ExternalMemoryHandleType::ZirconVmo => result.zircon_vmo = true,
ExternalMemoryHandleType::RdmaAddress => result.rdma_address = true,
}
result
}
}
impl ExternalMemoryHandleTypes {
/// Returns an iterator of `ExternalMemoryHandleType` enum values, representing the fields that
/// are set in `self`.
#[inline]
pub fn iter(&self) -> impl Iterator<Item = ExternalMemoryHandleType> {
let ExternalMemoryHandleTypes {
opaque_fd,
opaque_win32,
opaque_win32_kmt,
d3d11_texture,
d3d11_texture_kmt,
d3d12_heap,
d3d12_resource,
dma_buf,
android_hardware_buffer,
host_allocation,
host_mapped_foreign_memory,
zircon_vmo,
rdma_address,
_ne: _,
} = *self;
[
opaque_fd.then_some(ExternalMemoryHandleType::OpaqueFd),
opaque_win32.then_some(ExternalMemoryHandleType::OpaqueWin32),
opaque_win32_kmt.then_some(ExternalMemoryHandleType::OpaqueWin32Kmt),
d3d11_texture.then_some(ExternalMemoryHandleType::D3D11Texture),
d3d11_texture_kmt.then_some(ExternalMemoryHandleType::D3D11TextureKmt),
d3d12_heap.then_some(ExternalMemoryHandleType::D3D12Heap),
d3d12_resource.then_some(ExternalMemoryHandleType::D3D12Resource),
dma_buf.then_some(ExternalMemoryHandleType::DmaBuf),
android_hardware_buffer.then_some(ExternalMemoryHandleType::AndroidHardwareBuffer),
host_allocation.then_some(ExternalMemoryHandleType::HostAllocation),
host_mapped_foreign_memory.then_some(ExternalMemoryHandleType::HostMappedForeignMemory),
zircon_vmo.then_some(ExternalMemoryHandleType::HostMappedForeignMemory),
rdma_address.then_some(ExternalMemoryHandleType::HostMappedForeignMemory),
]
.into_iter()
.flatten()
}
}
vulkan_bitflags! {
/// A mask specifying flags for device memory allocation. /// A mask specifying flags for device memory allocation.
#[non_exhaustive]
MemoryAllocateFlags = MemoryAllocateFlags(u32); MemoryAllocateFlags = MemoryAllocateFlags(u32);
// TODO: implement // TODO: implement
// device_mask = DEVICE_MASK, // device_mask = DEVICE_MASK,
/// Specifies that the allocated device memory can be bound to a buffer created with the /// Specifies that the allocated device memory can be bound to a buffer created with the
/// [`shader_device_address`] usage. This requires that the [`buffer_device_address`] feature /// [`SHADER_DEVICE_ADDRESS`] usage. This requires that the [`buffer_device_address`] feature
/// is enabled on the device and the [`ext_buffer_device_address`] extension is not enabled on /// is enabled on the device and the [`ext_buffer_device_address`] extension is not enabled on
/// the device. /// the device.
/// ///
/// [`shader_device_address`]: crate::buffer::BufferUsage::shader_device_address /// [`SHADER_DEVICE_ADDRESS`]: crate::buffer::BufferUsage::SHADER_DEVICE_ADDRESS
/// [`buffer_device_address`]: crate::device::Features::buffer_device_address /// [`buffer_device_address`]: crate::device::Features::buffer_device_address
/// [`ext_buffer_device_address`]: crate::device::DeviceExtensions::ext_buffer_device_address /// [`ext_buffer_device_address`]: crate::device::DeviceExtensions::ext_buffer_device_address
device_address = DEVICE_ADDRESS, DEVICE_ADDRESS = DEVICE_ADDRESS,
// TODO: implement // TODO: implement
// device_address_capture_replay = DEVICE_ADDRESS_CAPTURE_REPLAY, // device_address_capture_replay = DEVICE_ADDRESS_CAPTURE_REPLAY,
@ -1119,8 +1008,10 @@ pub enum DeviceMemoryError {
memory_type_count: u32, memory_type_count: u32,
}, },
/// The memory type from which this memory was allocated does not have the /// The memory type from which this memory was allocated does not have the [`LAZILY_ALLOCATED`]
/// [`lazily_allocated`](crate::memory::MemoryPropertyFlags::lazily_allocated) flag set. /// flag set.
///
/// [`LAZILY_ALLOCATED`]: crate::memory::MemoryPropertyFlags::LAZILY_ALLOCATED
NotLazilyAllocated, NotLazilyAllocated,
/// Spec violation, containing the Valid Usage ID (VUID) from the Vulkan spec. /// Spec violation, containing the Valid Usage ID (VUID) from the Vulkan spec.
@ -1259,7 +1150,7 @@ impl From<RequirementNotMet> for DeviceMemoryError {
/// # Examples /// # Examples
/// ///
/// ``` /// ```
/// use vulkano::memory::{DeviceMemory, MappedDeviceMemory, MemoryAllocateInfo}; /// use vulkano::memory::{DeviceMemory, MappedDeviceMemory, MemoryAllocateInfo, MemoryPropertyFlags};
/// ///
/// # let device: std::sync::Arc<vulkano::device::Device> = return; /// # let device: std::sync::Arc<vulkano::device::Device> = return;
/// // The memory type must be mappable. /// // The memory type must be mappable.
@ -1268,7 +1159,7 @@ impl From<RequirementNotMet> for DeviceMemoryError {
/// .memory_properties() /// .memory_properties()
/// .memory_types /// .memory_types
/// .iter() /// .iter()
/// .position(|t| t.property_flags.host_visible) /// .position(|t| t.property_flags.intersects(MemoryPropertyFlags::HOST_VISIBLE))
/// .map(|i| i as u32) /// .map(|i| i as u32)
/// .unwrap(); // Vk specs guarantee that this can't fail /// .unwrap(); // Vk specs guarantee that this can't fail
/// ///
@ -1342,11 +1233,16 @@ impl MappedDeviceMemory {
[memory.memory_type_index() as usize]; [memory.memory_type_index() as usize];
// VUID-vkMapMemory-memory-00682 // VUID-vkMapMemory-memory-00682
if !memory_type.property_flags.host_visible { if !memory_type
.property_flags
.intersects(MemoryPropertyFlags::HOST_VISIBLE)
{
return Err(MemoryMapError::NotHostVisible); return Err(MemoryMapError::NotHostVisible);
} }
let coherent = memory_type.property_flags.host_coherent; let coherent = memory_type
.property_flags
.intersects(MemoryPropertyFlags::HOST_COHERENT);
let atom_size = device.physical_device().properties().non_coherent_atom_size; let atom_size = device.physical_device().properties().non_coherent_atom_size;
// Not required for merely mapping, but without this check the user can end up with // Not required for merely mapping, but without this check the user can end up with
@ -1687,7 +1583,7 @@ impl From<OomError> for MemoryMapError {
mod tests { mod tests {
use super::MemoryAllocateInfo; use super::MemoryAllocateInfo;
use crate::{ use crate::{
memory::{DeviceMemory, DeviceMemoryError}, memory::{DeviceMemory, DeviceMemoryError, MemoryPropertyFlags},
OomError, OomError,
}; };
@ -1731,7 +1627,11 @@ mod tests {
.memory_types .memory_types
.iter() .iter()
.enumerate() .enumerate()
.find_map(|(i, m)| (!m.property_flags.lazily_allocated).then_some(i as u32)) .find_map(|(i, m)| {
(!m.property_flags
.intersects(MemoryPropertyFlags::LAZILY_ALLOCATED))
.then_some(i as u32)
})
.unwrap(); .unwrap();
match DeviceMemory::allocate( match DeviceMemory::allocate(
@ -1757,7 +1657,11 @@ mod tests {
.memory_types .memory_types
.iter() .iter()
.enumerate() .enumerate()
.find_map(|(i, m)| (!m.property_flags.lazily_allocated).then_some((i as u32, m))) .find_map(|(i, m)| {
(!m.property_flags
.intersects(MemoryPropertyFlags::LAZILY_ALLOCATED))
.then_some((i as u32, m))
})
.unwrap(); .unwrap();
let heap_size = device.physical_device().memory_properties().memory_heaps let heap_size = device.physical_device().memory_properties().memory_heaps
[memory_type.heap_index as usize] [memory_type.heap_index as usize]

View File

@ -40,8 +40,7 @@
//! # let physical_device: vulkano::device::physical::PhysicalDevice = return; //! # let physical_device: vulkano::device::physical::PhysicalDevice = return;
//! for ty in physical_device.memory_properties().memory_types.iter() { //! for ty in physical_device.memory_properties().memory_types.iter() {
//! println!("Memory type belongs to heap #{:?}", ty.heap_index); //! println!("Memory type belongs to heap #{:?}", ty.heap_index);
//! println!("Host-accessible: {:?}", ty.property_flags.host_visible); //! println!("Property flags: {:?}", ty.property_flags);
//! println!("Device-local: {:?}", ty.property_flags.device_local);
//! } //! }
//! ``` //! ```
//! //!
@ -153,12 +152,13 @@ pub struct MemoryType {
} }
vulkan_bitflags! { vulkan_bitflags! {
/// Properties of a memory type.
#[non_exhaustive] #[non_exhaustive]
/// Properties of a memory type.
MemoryPropertyFlags = MemoryPropertyFlags(u32); MemoryPropertyFlags = MemoryPropertyFlags(u32);
/// The memory is located on the device, and is allocated from a heap that also has the /// The memory is located on the device, and is allocated from a heap that also has the
/// [`device_local`](MemoryHeapFlags::device_local) flag set. /// [`DEVICE_LOCAL`] flag set.
/// ///
/// For some devices, particularly integrated GPUs, the device shares memory with the host and /// For some devices, particularly integrated GPUs, the device shares memory with the host and
/// all memory may be device-local, so the distinction is moot. However, if the device has /// all memory may be device-local, so the distinction is moot. However, if the device has
@ -174,41 +174,50 @@ vulkan_bitflags! {
/// the speed difference may not be large. /// the speed difference may not be large.
/// ///
/// For data transfer between host and device, it is most efficient if the memory is located /// For data transfer between host and device, it is most efficient if the memory is located
/// at the destination of the transfer. Thus, if `host_visible` versions of both are available, /// at the destination of the transfer. Thus, if [`HOST_VISIBLE`] versions of both are
/// device-local memory is preferred for host-to-device data transfer, while non-device-local /// available, device-local memory is preferred for host-to-device data transfer, while
/// memory is preferred for device-to-host data transfer. This is because data is usually /// non-device-local memory is preferred for device-to-host data transfer. This is because data
/// written only once but potentially read several times, and because reads can take advantage /// is usually written only once but potentially read several times, and because reads can take
/// of caching while writes cannot. /// advantage of caching while writes cannot.
/// ///
/// Devices may have memory types that are neither `device_local` nor `host_visible`. This is /// Devices may have memory types that are neither `DEVICE_LOCAL` nor [`HOST_VISIBLE`]. This
/// regular host memory that is made available to the device exclusively. Although it will be /// is regular host memory that is made available to the device exclusively. Although it will be
/// slower to access from the device than `device_local` memory, it can be faster than /// slower to access from the device than `DEVICE_LOCAL` memory, it can be faster than
/// `host_visible` memory. It can be used as overflow space if the device is out of memory. /// [`HOST_VISIBLE`] memory. It can be used as overflow space if the device is out of memory.
device_local = DEVICE_LOCAL, ///
/// [`DEVICE_LOCAL`]: MemoryHeapFlags::DEVICE_LOCAL
/// [`HOST_VISIBLE`]: MemoryPropertyFlags::HOST_VISIBLE
DEVICE_LOCAL = DEVICE_LOCAL,
/// The memory can be mapped into the memory space of the host and accessed as regular RAM. /// The memory can be mapped into the memory space of the host and accessed as regular RAM.
/// ///
/// Memory of this type is required to transfer data between the host and the device. If /// Memory of this type is required to transfer data between the host and the device. If
/// the memory is going to be accessed by the device more than a few times, it is recommended /// the memory is going to be accessed by the device more than a few times, it is recommended
/// to copy the data to non-`host_visible` memory first if it is available. /// to copy the data to non-`HOST_VISIBLE` memory first if it is available.
/// ///
/// `host_visible` memory is always at least either `host_coherent` or `host_cached`, but it /// `HOST_VISIBLE` memory is always at least either [`HOST_COHERENT`] or [`HOST_CACHED`],
/// can be both. /// but it can be both.
host_visible = HOST_VISIBLE, ///
/// [`HOST_COHERENT`]: MemoryPropertyFlags::HOST_COHERENT
/// [`HOST_CACHED`]: MemoryPropertyFlags::HOST_CACHED
HOST_VISIBLE = HOST_VISIBLE,
/// Host access to the memory does not require calling /// Host access to the memory does not require calling [`invalidate_range`] to make device
/// [`invalidate_range`](MappedDeviceMemory::invalidate_range) to make device writes visible to /// writes visible to the host, nor [`flush_range`] to flush host writes back to the device.
/// the host, nor [`flush_range`](MappedDeviceMemory::flush_range) to flush host writes back ///
/// to the device. /// [`invalidate_range`]: MappedDeviceMemory::invalidate_range
host_coherent = HOST_COHERENT, /// [`flush_range`]: MappedDeviceMemory::flush_range
HOST_COHERENT = HOST_COHERENT,
/// The memory is cached by the host. /// The memory is cached by the host.
/// ///
/// `host_cached` memory is fast for reads and random access from the host, so it is preferred /// `HOST_CACHED` memory is fast for reads and random access from the host, so it is preferred
/// for device-to-host data transfer. Memory that is `host_visible` but not `host_cached` is /// for device-to-host data transfer. Memory that is [`HOST_VISIBLE`] but not `HOST_CACHED` is
/// often slow for all accesses other than sequential writing, so it is more suited for /// often slow for all accesses other than sequential writing, so it is more suited for
/// host-to-device transfer, and it is often beneficial to write the data in sequence. /// host-to-device transfer, and it is often beneficial to write the data in sequence.
host_cached = HOST_CACHED, ///
/// [`HOST_VISIBLE`]: MemoryPropertyFlags::HOST_VISIBLE
HOST_CACHED = HOST_CACHED,
/// Allocations made from the memory are lazy. /// Allocations made from the memory are lazy.
/// ///
@ -218,13 +227,19 @@ vulkan_bitflags! {
/// allocation. /// allocation.
/// ///
/// Memory of this type can only be used on images created with a certain flag, and is never /// Memory of this type can only be used on images created with a certain flag, and is never
/// `host_visible`. /// [`HOST_VISIBLE`].
lazily_allocated = LAZILY_ALLOCATED, ///
/// [`HOST_VISIBLE`]: MemoryPropertyFlags::HOST_VISIBLE
LAZILY_ALLOCATED = LAZILY_ALLOCATED,
/// The memory can only be accessed by the device, and allows protected queue access. /// The memory can only be accessed by the device, and allows protected queue access.
/// ///
/// Memory of this type is never `host_visible`, `host_coherent` or `host_cached`. /// Memory of this type is never [`HOST_VISIBLE`], [`HOST_COHERENT`] or [`HOST_CACHED`].
protected = PROTECTED { ///
/// [`HOST_VISIBLE`]: MemoryPropertyFlags::HOST_VISIBLE
/// [`HOST_COHERENT`]: MemoryPropertyFlags::HOST_COHERENT
/// [`HOST_CACHED`]: MemoryPropertyFlags::HOST_CACHED
PROTECTED = PROTECTED {
api_version: V1_1, api_version: V1_1,
}, },
@ -233,19 +248,21 @@ vulkan_bitflags! {
/// ///
/// Memory of this type is slower to access by the device, so it is best avoided for general /// Memory of this type is slower to access by the device, so it is best avoided for general
/// purpose use. Because of its coherence properties, however, it may be useful for debugging. /// purpose use. Because of its coherence properties, however, it may be useful for debugging.
device_coherent = DEVICE_COHERENT_AMD { DEVICE_COHERENT = DEVICE_COHERENT_AMD {
device_extensions: [amd_device_coherent_memory], device_extensions: [amd_device_coherent_memory],
}, },
/// The memory is not cached on the device. /// The memory is not cached on the device.
/// ///
/// `device_uncached` memory is always also `device_coherent`. /// `DEVICE_UNCACHED` memory is always also [`DEVICE_COHERENT`].
device_uncached = DEVICE_UNCACHED_AMD { ///
/// [`DEVICE_COHERENT`]: MemoryPropertyFlags::DEVICE_COHERENT
DEVICE_UNCACHED = DEVICE_UNCACHED_AMD {
device_extensions: [amd_device_coherent_memory], device_extensions: [amd_device_coherent_memory],
}, },
/// Other devices can access the memory via remote direct memory access (RDMA). /// Other devices can access the memory via remote direct memory access (RDMA).
rdma_capable = RDMA_CAPABLE_NV { RDMA_CAPABLE = RDMA_CAPABLE_NV {
device_extensions: [nv_external_memory_rdma], device_extensions: [nv_external_memory_rdma],
}, },
} }
@ -262,16 +279,17 @@ pub struct MemoryHeap {
} }
vulkan_bitflags! { vulkan_bitflags! {
/// Attributes of a memory heap.
#[non_exhaustive] #[non_exhaustive]
/// Attributes of a memory heap.
MemoryHeapFlags = MemoryHeapFlags(u32); MemoryHeapFlags = MemoryHeapFlags(u32);
/// The heap corresponds to device-local memory. /// The heap corresponds to device-local memory.
device_local = DEVICE_LOCAL, DEVICE_LOCAL = DEVICE_LOCAL,
/// If used on a logical device that represents more than one physical device, allocations are /// If used on a logical device that represents more than one physical device, allocations are
/// replicated across each physical device's instance of this heap. /// replicated across each physical device's instance of this heap.
multi_instance = MULTI_INSTANCE { MULTI_INSTANCE = MULTI_INSTANCE {
api_version: V1_1, api_version: V1_1,
instance_extensions: [khr_device_group_creation], instance_extensions: [khr_device_group_creation],
}, },

View File

@ -491,10 +491,7 @@ mod tests {
let memory_allocator = StandardMemoryAllocator::new_default(device.clone()); let memory_allocator = StandardMemoryAllocator::new_default(device.clone());
let data_buffer = CpuAccessibleBuffer::from_data( let data_buffer = CpuAccessibleBuffer::from_data(
&memory_allocator, &memory_allocator,
BufferUsage { BufferUsage::STORAGE_BUFFER,
storage_buffer: true,
..BufferUsage::empty()
},
false, false,
0, 0,
) )

View File

@ -34,7 +34,8 @@ use super::{
use crate::{ use crate::{
descriptor_set::layout::{DescriptorSetLayout, DescriptorSetLayoutCreateInfo}, descriptor_set::layout::{DescriptorSetLayout, DescriptorSetLayoutCreateInfo},
device::{Device, DeviceOwned}, device::{Device, DeviceOwned},
format::NumericType, format::{FormatFeatures, NumericType},
image::ImageAspects,
pipeline::{ pipeline::{
cache::PipelineCache, cache::PipelineCache,
graphics::{ graphics::{
@ -484,7 +485,8 @@ where
// VUID-VkGraphicsPipelineCreateInfo-multiview-06577 // VUID-VkGraphicsPipelineCreateInfo-multiview-06577
if view_mask != 0 && !device.enabled_features().multiview { if view_mask != 0 && !device.enabled_features().multiview {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: "`render_pass` is `PipelineRenderPassType::BeginRendering` where `view_mask` is not `0`", required_for: "`render_pass` is `PipelineRenderPassType::BeginRendering` \
where `view_mask` is not `0`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["multiview"], features: &["multiview"],
..Default::default() ..Default::default()
@ -519,7 +521,7 @@ where
// Use unchecked, because all validation has been done above. // Use unchecked, because all validation has been done above.
if !unsafe { physical_device.format_properties_unchecked(format) } if !unsafe { physical_device.format_properties_unchecked(format) }
.potential_format_features() .potential_format_features()
.color_attachment .intersects(FormatFeatures::COLOR_ATTACHMENT)
{ {
return Err( return Err(
GraphicsPipelineCreationError::ColorAttachmentFormatUsageNotSupported { GraphicsPipelineCreationError::ColorAttachmentFormatUsageNotSupported {
@ -537,7 +539,7 @@ where
// Use unchecked, because all validation has been done above. // Use unchecked, because all validation has been done above.
if !unsafe { physical_device.format_properties_unchecked(format) } if !unsafe { physical_device.format_properties_unchecked(format) }
.potential_format_features() .potential_format_features()
.depth_stencil_attachment .intersects(FormatFeatures::DEPTH_STENCIL_ATTACHMENT)
{ {
return Err( return Err(
GraphicsPipelineCreationError::DepthAttachmentFormatUsageNotSupported, GraphicsPipelineCreationError::DepthAttachmentFormatUsageNotSupported,
@ -545,7 +547,7 @@ where
} }
// VUID-VkGraphicsPipelineCreateInfo-renderPass-06587 // VUID-VkGraphicsPipelineCreateInfo-renderPass-06587
if !format.aspects().depth { if !format.aspects().intersects(ImageAspects::DEPTH) {
return Err( return Err(
GraphicsPipelineCreationError::DepthAttachmentFormatUsageNotSupported, GraphicsPipelineCreationError::DepthAttachmentFormatUsageNotSupported,
); );
@ -560,7 +562,7 @@ where
// Use unchecked, because all validation has been done above. // Use unchecked, because all validation has been done above.
if !unsafe { physical_device.format_properties_unchecked(format) } if !unsafe { physical_device.format_properties_unchecked(format) }
.potential_format_features() .potential_format_features()
.depth_stencil_attachment .intersects(FormatFeatures::DEPTH_STENCIL_ATTACHMENT)
{ {
return Err( return Err(
GraphicsPipelineCreationError::StencilAttachmentFormatUsageNotSupported, GraphicsPipelineCreationError::StencilAttachmentFormatUsageNotSupported,
@ -568,7 +570,7 @@ where
} }
// VUID-VkGraphicsPipelineCreateInfo-renderPass-06588 // VUID-VkGraphicsPipelineCreateInfo-renderPass-06588
if !format.aspects().stencil { if !format.aspects().intersects(ImageAspects::STENCIL) {
return Err( return Err(
GraphicsPipelineCreationError::StencilAttachmentFormatUsageNotSupported, GraphicsPipelineCreationError::StencilAttachmentFormatUsageNotSupported,
); );
@ -663,7 +665,9 @@ where
.vertex_attribute_instance_rate_divisor .vertex_attribute_instance_rate_divisor
{ {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: "`vertex_input_state.bindings` has an element where `input_rate` is `VertexInputRate::Instance`, where `divisor` is not `1`", required_for: "`vertex_input_state.bindings` has an element \
where `input_rate` is `VertexInputRate::Instance`, where \
`divisor` is not `1`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["vertex_attribute_instance_rate_divisor"], features: &["vertex_attribute_instance_rate_divisor"],
..Default::default() ..Default::default()
@ -678,7 +682,9 @@ where
.vertex_attribute_instance_rate_zero_divisor .vertex_attribute_instance_rate_zero_divisor
{ {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: "`vertex_input_state.bindings` has an element where `input_rate` is `VertexInputRate::Instance`, where `divisor` is `0`", required_for: "`vertex_input_state.bindings` has an element \
where `input_rate` is `VertexInputRate::Instance`, where \
`divisor` is `0`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["vertex_attribute_instance_rate_zero_divisor"], features: &["vertex_attribute_instance_rate_zero_divisor"],
..Default::default() ..Default::default()
@ -754,7 +760,7 @@ where
}; };
// VUID-VkVertexInputAttributeDescription-format-00623 // VUID-VkVertexInputAttributeDescription-format-00623
if !format_features.vertex_buffer { if !format_features.intersects(FormatFeatures::VERTEX_BUFFER) {
return Err( return Err(
GraphicsPipelineCreationError::VertexInputAttributeUnsupportedFormat { GraphicsPipelineCreationError::VertexInputAttributeUnsupportedFormat {
location, location,
@ -805,9 +811,8 @@ where
&& !device.enabled_features().triangle_fans && !device.enabled_features().triangle_fans
{ {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: required_for: "this device is a portability subset \
"this device is a portability subset device, and \ device, and `input_assembly_state.topology` is \
`input_assembly_state.topology` is \
`StateMode::Fixed(PrimitiveTopology::TriangleFan)`", `StateMode::Fixed(PrimitiveTopology::TriangleFan)`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["triangle_fans"], features: &["triangle_fans"],
@ -823,7 +828,8 @@ where
// VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00429 // VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00429
if !device.enabled_features().geometry_shader { if !device.enabled_features().geometry_shader {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: "`input_assembly_state.topology` is `StateMode::Fixed(PrimitiveTopology::*WithAdjacency)`", required_for: "`input_assembly_state.topology` is \
`StateMode::Fixed(PrimitiveTopology::*WithAdjacency)`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["geometry_shader"], features: &["geometry_shader"],
..Default::default() ..Default::default()
@ -835,7 +841,8 @@ where
// VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00430 // VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00430
if !device.enabled_features().tessellation_shader { if !device.enabled_features().tessellation_shader {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: "`input_assembly_state.topology` is `StateMode::Fixed(PrimitiveTopology::PatchList)`", required_for: "`input_assembly_state.topology` is \
`StateMode::Fixed(PrimitiveTopology::PatchList)`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["tessellation_shader"], features: &["tessellation_shader"],
..Default::default() ..Default::default()
@ -858,8 +865,8 @@ where
|| device.enabled_features().extended_dynamic_state) || device.enabled_features().extended_dynamic_state)
{ {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: required_for: "`input_assembly_state.topology` is \
"`input_assembly_state.topology` is `PartialStateMode::Dynamic`", `PartialStateMode::Dynamic`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
api_version: Some(Version::V1_3), api_version: Some(Version::V1_3),
features: &["extended_dynamic_state"], features: &["extended_dynamic_state"],
@ -884,7 +891,10 @@ where
// VUID-VkPipelineInputAssemblyStateCreateInfo-topology-06252 // VUID-VkPipelineInputAssemblyStateCreateInfo-topology-06252
if !device.enabled_features().primitive_topology_list_restart { if !device.enabled_features().primitive_topology_list_restart {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: "`input_assembly_state.primitive_restart_enable` is `StateMode::Fixed(true)` and `input_assembly_state.topology` is `StateMode::Fixed(PrimitiveTopology::*List)`", required_for: "`input_assembly_state.primitive_restart_enable` \
is `StateMode::Fixed(true)` and \
`input_assembly_state.topology` is \
`StateMode::Fixed(PrimitiveTopology::*List)`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["primitive_topology_list_restart"], features: &["primitive_topology_list_restart"],
..Default::default() ..Default::default()
@ -899,7 +909,10 @@ where
.primitive_topology_patch_list_restart .primitive_topology_patch_list_restart
{ {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: "`input_assembly_state.primitive_restart_enable` is `StateMode::Fixed(true)` and `input_assembly_state.topology` is `StateMode::Fixed(PrimitiveTopology::PatchList)`", required_for: "`input_assembly_state.primitive_restart_enable` \
is `StateMode::Fixed(true)` and \
`input_assembly_state.topology` is \
`StateMode::Fixed(PrimitiveTopology::PatchList)`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["primitive_topology_patch_list_restart"], features: &["primitive_topology_patch_list_restart"],
..Default::default() ..Default::default()
@ -917,7 +930,8 @@ where
|| device.enabled_features().extended_dynamic_state2) || device.enabled_features().extended_dynamic_state2)
{ {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: "`input_assembly_state.primitive_restart_enable` is `StateMode::Dynamic`", required_for: "`input_assembly_state.primitive_restart_enable` is \
`StateMode::Dynamic`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
api_version: Some(Version::V1_3), api_version: Some(Version::V1_3),
features: &["extended_dynamic_state2"], features: &["extended_dynamic_state2"],
@ -1089,7 +1103,8 @@ where
// VUID-VkGraphicsPipelineCreateInfo-renderPass-06057 // VUID-VkGraphicsPipelineCreateInfo-renderPass-06057
if view_mask != 0 { if view_mask != 0 {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: "`tessellation_shaders` are provided and `render_pass` has a subpass where `view_mask` is not `0`", required_for: "`tessellation_shaders` are provided and `render_pass` \
has a subpass where `view_mask` is not `0`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["multiview_tessellation_shader"], features: &["multiview_tessellation_shader"],
..Default::default() ..Default::default()
@ -1158,7 +1173,8 @@ where
// VUID-VkGraphicsPipelineCreateInfo-renderPass-06058 // VUID-VkGraphicsPipelineCreateInfo-renderPass-06058
if view_mask != 0 { if view_mask != 0 {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: "`geometry_shader` is provided and `render_pass` has a subpass where `view_mask` is not `0`", required_for: "`geometry_shader` is provided and `render_pass` has a \
subpass where `view_mask` is not `0`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["multiview_geometry_shader"], features: &["multiview_geometry_shader"],
..Default::default() ..Default::default()
@ -1209,7 +1225,8 @@ where
|| device.enabled_features().extended_dynamic_state2) || device.enabled_features().extended_dynamic_state2)
{ {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: "`rasterization_state.rasterizer_discard_enable` is `StateMode::Dynamic`", required_for: "`rasterization_state.rasterizer_discard_enable` is \
`StateMode::Dynamic`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
api_version: Some(Version::V1_3), api_version: Some(Version::V1_3),
features: &["extended_dynamic_state"], features: &["extended_dynamic_state"],
@ -1244,8 +1261,8 @@ where
&& !device.enabled_features().fill_mode_non_solid && !device.enabled_features().fill_mode_non_solid
{ {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: required_for: "`rasterization_state.polygon_mode` is not \
"`rasterization_state.polygon_mode` is not `PolygonMode::Fill`", `PolygonMode::Fill`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["fill_mode_non_solid"], features: &["fill_mode_non_solid"],
..Default::default() ..Default::default()
@ -1264,8 +1281,8 @@ where
|| device.enabled_features().extended_dynamic_state) || device.enabled_features().extended_dynamic_state)
{ {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: required_for: "`rasterization_state.cull_mode` is \
"`rasterization_state.cull_mode` is `StateMode::Dynamic`", `StateMode::Dynamic`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
api_version: Some(Version::V1_3), api_version: Some(Version::V1_3),
features: &["extended_dynamic_state"], features: &["extended_dynamic_state"],
@ -1287,8 +1304,8 @@ where
|| device.enabled_features().extended_dynamic_state) || device.enabled_features().extended_dynamic_state)
{ {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: required_for: "`rasterization_state.front_face` is \
"`rasterization_state.front_face` is `StateMode::Dynamic`", `StateMode::Dynamic`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
api_version: Some(Version::V1_3), api_version: Some(Version::V1_3),
features: &["extended_dynamic_state"], features: &["extended_dynamic_state"],
@ -1311,7 +1328,9 @@ where
|| device.enabled_features().extended_dynamic_state2) || device.enabled_features().extended_dynamic_state2)
{ {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: "`rasterization_state.depth_bias` is `Some(depth_bias_state)`, where `depth_bias_state.enable_dynamic` is set", required_for: "`rasterization_state.depth_bias` is \
`Some(depth_bias_state)`, where `depth_bias_state.enable_dynamic` \
is set",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
api_version: Some(Version::V1_3), api_version: Some(Version::V1_3),
features: &["extended_dynamic_state2"], features: &["extended_dynamic_state2"],
@ -1325,7 +1344,9 @@ where
&& !device.enabled_features().depth_bias_clamp && !device.enabled_features().depth_bias_clamp
{ {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: "`rasterization_state.depth_bias` is `Some(depth_bias_state)`, where `depth_bias_state.bias` is `StateMode::Fixed(bias)`, where `bias.clamp` is not `0.0`", required_for: "`rasterization_state.depth_bias` is \
`Some(depth_bias_state)`, where `depth_bias_state.bias` is \
`StateMode::Fixed(bias)`, where `bias.clamp` is not `0.0`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["depth_bias_clamp"], features: &["depth_bias_clamp"],
..Default::default() ..Default::default()
@ -1339,7 +1360,8 @@ where
&& !device.enabled_features().wide_lines && !device.enabled_features().wide_lines
{ {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: "`rasterization_state.line_width` is `StateMode::Fixed(line_width)`, where `line_width` is not `1.0`", required_for: "`rasterization_state.line_width` is \
`StateMode::Fixed(line_width)`, where `line_width` is not `1.0`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["wide_lines"], features: &["wide_lines"],
..Default::default() ..Default::default()
@ -1357,7 +1379,8 @@ where
// VUID-VkPipelineRasterizationLineStateCreateInfoEXT-lineRasterizationMode-02768 // VUID-VkPipelineRasterizationLineStateCreateInfoEXT-lineRasterizationMode-02768
if !device.enabled_features().rectangular_lines { if !device.enabled_features().rectangular_lines {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: "`rasterization_state.line_rasterization_mode` is `LineRasterizationMode::Rectangular`", required_for: "`rasterization_state.line_rasterization_mode` \
is `LineRasterizationMode::Rectangular`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["rectangular_lines"], features: &["rectangular_lines"],
..Default::default() ..Default::default()
@ -1369,7 +1392,8 @@ where
// VUID-VkPipelineRasterizationLineStateCreateInfoEXT-lineRasterizationMode-02769 // VUID-VkPipelineRasterizationLineStateCreateInfoEXT-lineRasterizationMode-02769
if !device.enabled_features().bresenham_lines { if !device.enabled_features().bresenham_lines {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: "`rasterization_state.line_rasterization_mode` is `LineRasterizationMode::Bresenham`", required_for: "`rasterization_state.line_rasterization_mode` \
is `LineRasterizationMode::Bresenham`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["bresenham_lines"], features: &["bresenham_lines"],
..Default::default() ..Default::default()
@ -1381,7 +1405,8 @@ where
// VUID-VkPipelineRasterizationLineStateCreateInfoEXT-lineRasterizationMode-02770 // VUID-VkPipelineRasterizationLineStateCreateInfoEXT-lineRasterizationMode-02770
if !device.enabled_features().smooth_lines { if !device.enabled_features().smooth_lines {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: "`rasterization_state.line_rasterization_mode` is `LineRasterizationMode::RectangularSmooth`", required_for: "`rasterization_state.line_rasterization_mode` \
is `LineRasterizationMode::RectangularSmooth`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["smooth_lines"], features: &["smooth_lines"],
..Default::default() ..Default::default()
@ -1397,7 +1422,10 @@ where
// VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02774 // VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02774
if !device.enabled_features().stippled_rectangular_lines { if !device.enabled_features().stippled_rectangular_lines {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: "`rasterization_state.line_stipple` is `Some` and `rasterization_state.line_rasterization_mode` is `LineRasterizationMode::Default`", required_for: "`rasterization_state.line_stipple` is \
`Some` and \
`rasterization_state.line_rasterization_mode` \
is `LineRasterizationMode::Default`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["stippled_rectangular_lines"], features: &["stippled_rectangular_lines"],
..Default::default() ..Default::default()
@ -1416,7 +1444,10 @@ where
// VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02771 // VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02771
if !device.enabled_features().stippled_rectangular_lines { if !device.enabled_features().stippled_rectangular_lines {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: "`rasterization_state.line_stipple` is `Some` and `rasterization_state.line_rasterization_mode` is `LineRasterizationMode::Rectangular`", required_for: "`rasterization_state.line_stipple` is \
`Some` and \
`rasterization_state.line_rasterization_mode` \
is `LineRasterizationMode::Rectangular`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["stippled_rectangular_lines"], features: &["stippled_rectangular_lines"],
..Default::default() ..Default::default()
@ -1428,7 +1459,10 @@ where
// VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02772 // VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02772
if !device.enabled_features().stippled_bresenham_lines { if !device.enabled_features().stippled_bresenham_lines {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: "`rasterization_state.line_stipple` is `Some` and `rasterization_state.line_rasterization_mode` is `LineRasterizationMode::Bresenham`", required_for: "`rasterization_state.line_stipple` is \
`Some` and \
`rasterization_state.line_rasterization_mode` \
is `LineRasterizationMode::Bresenham`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["stippled_bresenham_lines"], features: &["stippled_bresenham_lines"],
..Default::default() ..Default::default()
@ -1440,7 +1474,10 @@ where
// VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02773 // VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02773
if !device.enabled_features().stippled_smooth_lines { if !device.enabled_features().stippled_smooth_lines {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: "`rasterization_state.line_stipple` is `Some` and `rasterization_state.line_rasterization_mode` is `LineRasterizationMode::RectangularSmooth`", required_for: "`rasterization_state.line_stipple` is \
`Some` and \
`rasterization_state.line_rasterization_mode` \
is `LineRasterizationMode::RectangularSmooth`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["stippled_smooth_lines"], features: &["stippled_smooth_lines"],
..Default::default() ..Default::default()
@ -1459,7 +1496,8 @@ where
} else { } else {
if line_rasterization_mode != LineRasterizationMode::Default { if line_rasterization_mode != LineRasterizationMode::Default {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: "`rasterization_state.line_rasterization_mode` is not `LineRasterizationMode::Default`", required_for: "`rasterization_state.line_rasterization_mode` is not \
`LineRasterizationMode::Default`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
device_extensions: &["ext_line_rasterization"], device_extensions: &["ext_line_rasterization"],
..Default::default() ..Default::default()
@ -1509,7 +1547,8 @@ where
if error { if error {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: "`discard_rectangle_state.rectangles` is not `PartialStateMode::Fixed(vec![])`", required_for: "`discard_rectangle_state.rectangles` is not \
`PartialStateMode::Fixed(vec![])`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
device_extensions: &["ext_discard_rectangles"], device_extensions: &["ext_discard_rectangles"],
..Default::default() ..Default::default()
@ -1559,8 +1598,8 @@ where
.extended_dynamic_state2_patch_control_points .extended_dynamic_state2_patch_control_points
{ {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: required_for: "`tessellation_state.patch_control_points` is \
"`tessellation_state.patch_control_points` is `StateMode::Dynamic`", `StateMode::Dynamic`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["extended_dynamic_state2_patch_control_points"], features: &["extended_dynamic_state2_patch_control_points"],
..Default::default() ..Default::default()
@ -1637,7 +1676,9 @@ where
|| device.enabled_features().extended_dynamic_state) || device.enabled_features().extended_dynamic_state)
{ {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: "`viewport_state` is `ViewportState::FixedViewport`, where `scissor_count_dynamic` is set", required_for: "`viewport_state` is \
`ViewportState::FixedViewport`, where `scissor_count_dynamic` \
is set",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
api_version: Some(Version::V1_3), api_version: Some(Version::V1_3),
features: &["extended_dynamic_state"], features: &["extended_dynamic_state"],
@ -1669,7 +1710,9 @@ where
|| device.enabled_features().extended_dynamic_state) || device.enabled_features().extended_dynamic_state)
{ {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: "`viewport_state` is `ViewportState::FixedScissor`, where `viewport_count_dynamic` is set", required_for: "`viewport_state` is \
`ViewportState::FixedScissor`, where `viewport_count_dynamic` \
is set",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
api_version: Some(Version::V1_3), api_version: Some(Version::V1_3),
features: &["extended_dynamic_state"], features: &["extended_dynamic_state"],
@ -1707,7 +1750,9 @@ where
|| device.enabled_features().extended_dynamic_state) || device.enabled_features().extended_dynamic_state)
{ {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: "`viewport_state` is `ViewportState::Dynamic`, where `viewport_count_dynamic` is set", required_for: "`viewport_state` is \
`ViewportState::Dynamic`, where `viewport_count_dynamic` \
is set",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
api_version: Some(Version::V1_3), api_version: Some(Version::V1_3),
features: &["extended_dynamic_state"], features: &["extended_dynamic_state"],
@ -1728,7 +1773,9 @@ where
|| device.enabled_features().extended_dynamic_state) || device.enabled_features().extended_dynamic_state)
{ {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: "`viewport_state` is `ViewportState::Dynamic`, where `scissor_count_dynamic` is set", required_for: "`viewport_state` is \
`ViewportState::Dynamic`, where `scissor_count_dynamic` \
is set",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
api_version: Some(Version::V1_3), api_version: Some(Version::V1_3),
features: &["extended_dynamic_state"], features: &["extended_dynamic_state"],
@ -1756,7 +1803,8 @@ where
// VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217 // VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217
if viewport_scissor_count > 1 && !device.enabled_features().multi_viewport { if viewport_scissor_count > 1 && !device.enabled_features().multi_viewport {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: "`viewport_state` has a fixed viewport/scissor count that is greater than `1`", required_for: "`viewport_state` has a fixed viewport/scissor count that is \
greater than `1`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["multi_viewport"], features: &["multi_viewport"],
..Default::default() ..Default::default()
@ -1867,8 +1915,8 @@ where
|| device.enabled_features().extended_dynamic_state) || device.enabled_features().extended_dynamic_state)
{ {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: required_for: "`depth_stencil_state.depth` is `Some(depth_state)`, where \
"`depth_stencil_state.depth` is `Some(depth_state)`, where `depth_state.enable_dynamic` is set", `depth_state.enable_dynamic` is set",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
api_version: Some(Version::V1_3), api_version: Some(Version::V1_3),
features: &["extended_dynamic_state"], features: &["extended_dynamic_state"],
@ -1897,7 +1945,9 @@ where
|| device.enabled_features().extended_dynamic_state) || device.enabled_features().extended_dynamic_state)
{ {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: "`depth_stencil_state.depth` is `Some(depth_state)`, where `depth_state.write_enable` is `StateMode::Dynamic`", required_for: "`depth_stencil_state.depth` is \
`Some(depth_state)`, where `depth_state.write_enable` is \
`StateMode::Dynamic`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
api_version: Some(Version::V1_3), api_version: Some(Version::V1_3),
features: &["extended_dynamic_state"], features: &["extended_dynamic_state"],
@ -1919,7 +1969,9 @@ where
|| device.enabled_features().extended_dynamic_state) || device.enabled_features().extended_dynamic_state)
{ {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: "`depth_stencil_state.depth` is `Some(depth_state)`, where `depth_state.compare_op` is `StateMode::Dynamic`", required_for: "`depth_stencil_state.depth` is \
`Some(depth_state)`, where `depth_state.compare_op` is \
`StateMode::Dynamic`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
api_version: Some(Version::V1_3), api_version: Some(Version::V1_3),
features: &["extended_dynamic_state"], features: &["extended_dynamic_state"],
@ -1954,7 +2006,9 @@ where
|| device.enabled_features().extended_dynamic_state) || device.enabled_features().extended_dynamic_state)
{ {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: "`depth_stencil_state.depth_bounds` is `Some(depth_bounds_state)`, where `depth_bounds_state.enable_dynamic` is set", required_for: "`depth_stencil_state.depth_bounds` is \
`Some(depth_bounds_state)`, where `depth_bounds_state.enable_dynamic` \
is set",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
api_version: Some(Version::V1_3), api_version: Some(Version::V1_3),
features: &["extended_dynamic_state"], features: &["extended_dynamic_state"],
@ -1970,7 +2024,9 @@ where
&& !(0.0..1.0).contains(bounds.end()) && !(0.0..1.0).contains(bounds.end())
{ {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: "`depth_stencil_state.depth_bounds` is `Some(depth_bounds_state)`, where `depth_bounds_state.bounds` is not between `0.0` and `1.0` inclusive", required_for: "`depth_stencil_state.depth_bounds` is \
`Some(depth_bounds_state)`, where `depth_bounds_state.bounds` is \
not between `0.0` and `1.0` inclusive",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
device_extensions: &["ext_depth_range_unrestricted"], device_extensions: &["ext_depth_range_unrestricted"],
..Default::default() ..Default::default()
@ -2004,8 +2060,8 @@ where
|| device.enabled_features().extended_dynamic_state) || device.enabled_features().extended_dynamic_state)
{ {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: required_for: "`depth_stencil_state.stencil` is `Some(stencil_state)`, \
"`depth_stencil_state.stencil` is `Some(stencil_state)`, where `stencil_state.enable_dynamic` is set", where `stencil_state.enable_dynamic` is set",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
api_version: Some(Version::V1_3), api_version: Some(Version::V1_3),
features: &["extended_dynamic_state"], features: &["extended_dynamic_state"],
@ -2043,7 +2099,9 @@ where
|| device.enabled_features().extended_dynamic_state) || device.enabled_features().extended_dynamic_state)
{ {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: "`depth_stencil_state.stencil` is `Some(stencil_state)`, where `stencil_state.front.ops` and `stencil_state.back.ops` are `StateMode::Dynamic`", required_for: "`depth_stencil_state.stencil` is \
`Some(stencil_state)`, where `stencil_state.front.ops` and \
`stencil_state.back.ops` are `StateMode::Dynamic`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
api_version: Some(Version::V1_3), api_version: Some(Version::V1_3),
features: &["extended_dynamic_state"], features: &["extended_dynamic_state"],
@ -2209,8 +2267,8 @@ where
// VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04869 // VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04869
if !device.enabled_features().extended_dynamic_state2_logic_op { if !device.enabled_features().extended_dynamic_state2_logic_op {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: required_for: "`color_blend_state.logic_op` is \
"`color_blend_state.logic_op` is `Some(StateMode::Dynamic)`", `Some(StateMode::Dynamic)`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["extended_dynamic_state2_logic_op"], features: &["extended_dynamic_state2_logic_op"],
..Default::default() ..Default::default()
@ -2247,7 +2305,8 @@ where
// VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605 // VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605
if !iter.all(|state| state == first) { if !iter.all(|state| state == first) {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: "`color_blend_state.attachments` has elements where `blend` and `color_write_mask` do not match the other elements", required_for: "`color_blend_state.attachments` has elements where \
`blend` and `color_write_mask` do not match the other elements",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["independent_blend"], features: &["independent_blend"],
..Default::default() ..Default::default()
@ -2312,9 +2371,9 @@ where
{ {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: "`color_blend_state.attachments` has an element where \ required_for: "`color_blend_state.attachments` has an element where \
`blend` is `Some(blend)`, where `blend.color_source`, \ `blend` is `Some(blend)`, where `blend.color_source`, \
`blend.color_destination`, `blend.alpha_source` or \ `blend.color_destination`, `blend.alpha_source` or \
`blend.alpha_destination` is `BlendFactor::Src1*`", `blend.alpha_destination` is `BlendFactor::Src1*`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["dual_src_blend"], features: &["dual_src_blend"],
..Default::default() ..Default::default()
@ -2344,7 +2403,7 @@ where
physical_device physical_device
.format_properties_unchecked(format) .format_properties_unchecked(format)
.potential_format_features() .potential_format_features()
.color_attachment_blend .intersects(FormatFeatures::COLOR_ATTACHMENT_BLEND)
}) { }) {
return Err( return Err(
GraphicsPipelineCreationError::ColorAttachmentFormatBlendNotSupported { GraphicsPipelineCreationError::ColorAttachmentFormatBlendNotSupported {
@ -2385,7 +2444,8 @@ where
// VUID-VkPipelineColorWriteCreateInfoEXT-pAttachments-04801 // VUID-VkPipelineColorWriteCreateInfoEXT-pAttachments-04801
if !enable && !device.enabled_features().color_write_enable { if !enable && !device.enabled_features().color_write_enable {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: "`color_blend_state.attachments` has an element where `color_write_enable` is `StateMode::Fixed(false)`", required_for: "`color_blend_state.attachments` has an element \
where `color_write_enable` is `StateMode::Fixed(false)`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["color_write_enable"], features: &["color_write_enable"],
..Default::default() ..Default::default()
@ -2397,7 +2457,8 @@ where
// VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04800 // VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04800
if !device.enabled_features().color_write_enable { if !device.enabled_features().color_write_enable {
return Err(GraphicsPipelineCreationError::RequirementNotMet { return Err(GraphicsPipelineCreationError::RequirementNotMet {
required_for: "`color_blend_state.attachments` has an element where `color_write_enable` is `StateMode::Dynamic`", required_for: "`color_blend_state.attachments` has an element \
where `color_write_enable` is `StateMode::Dynamic`",
requires_one_of: RequiresOneOf { requires_one_of: RequiresOneOf {
features: &["color_write_enable"], features: &["color_write_enable"],
..Default::default() ..Default::default()

View File

@ -144,6 +144,7 @@ impl Default for ColorBlendState {
} }
vulkan_enum! { vulkan_enum! {
#[non_exhaustive]
/// Which logical operation to apply to the output values. /// Which logical operation to apply to the output values.
/// ///
/// The operation is applied individually for each channel (red, green, blue and alpha). /// The operation is applied individually for each channel (red, green, blue and alpha).
@ -151,7 +152,6 @@ vulkan_enum! {
/// Only relevant for integer or unsigned attachments. /// Only relevant for integer or unsigned attachments.
/// ///
/// Also note that some implementations don't support logic operations. /// Also note that some implementations don't support logic operations.
#[non_exhaustive]
LogicOp = LogicOp(i32); LogicOp = LogicOp(i32);
/// Returns `0`. /// Returns `0`.
@ -318,6 +318,8 @@ impl From<AttachmentBlend> for ash::vk::PipelineColorBlendAttachmentState {
} }
vulkan_enum! { vulkan_enum! {
#[non_exhaustive]
/// The operation that takes `source` (output from the fragment shader), `destination` (value /// The operation that takes `source` (output from the fragment shader), `destination` (value
/// currently in the framebuffer attachment) and `blend_constant` input values, /// currently in the framebuffer attachment) and `blend_constant` input values,
/// and produces new inputs to be fed to `BlendOp`. /// and produces new inputs to be fed to `BlendOp`.
@ -325,7 +327,6 @@ vulkan_enum! {
/// Some operations take `source1` as an input, representing the second source value. The /// Some operations take `source1` as an input, representing the second source value. The
/// [`dual_src_blend`](crate::device::Features::dual_src_blend) feature must be enabled on the /// [`dual_src_blend`](crate::device::Features::dual_src_blend) feature must be enabled on the
/// device when these are used. /// device when these are used.
#[non_exhaustive]
BlendFactor = BlendFactor(i32); BlendFactor = BlendFactor(i32);
/// Always `0`. /// Always `0`.
@ -400,9 +401,10 @@ vulkan_enum! {
} }
vulkan_enum! { vulkan_enum! {
#[non_exhaustive]
/// The arithmetic operation that is applied between the `source` and `destination` component /// The arithmetic operation that is applied between the `source` and `destination` component
/// values, after the appropriate `BlendFactor` is applied to both. /// values, after the appropriate `BlendFactor` is applied to both.
#[non_exhaustive]
BlendOp = BlendOp(i32); BlendOp = BlendOp(i32);
/// `source + destination`. /// `source + destination`.
@ -658,14 +660,14 @@ vulkan_bitflags! {
ColorComponents = ColorComponentFlags(u32); ColorComponents = ColorComponentFlags(u32);
/// The red component. /// The red component.
r = R, R = R,
/// The green component. /// The green component.
g = G, G = G,
/// The blue component. /// The blue component.
b = B, B = B,
/// The alpha component. /// The alpha component.
a = A, A = A,
} }

View File

@ -251,8 +251,9 @@ impl Default for StencilOps {
} }
vulkan_enum! { vulkan_enum! {
/// Operation to perform after the depth and stencil tests.
#[non_exhaustive] #[non_exhaustive]
/// Operation to perform after the depth and stencil tests.
StencilOp = StencilOp(i32); StencilOp = StencilOp(i32);
// TODO: document // TODO: document
@ -281,8 +282,9 @@ vulkan_enum! {
} }
vulkan_enum! { vulkan_enum! {
/// Specifies a face for stencil operations.
#[non_exhaustive] #[non_exhaustive]
/// Specifies a face for stencil operations.
StencilFaces = StencilFaceFlags(u32); StencilFaces = StencilFaceFlags(u32);
// TODO: document // TODO: document
@ -303,10 +305,11 @@ pub struct DynamicStencilValue {
} }
vulkan_enum! { vulkan_enum! {
#[non_exhaustive]
/// Specifies how two values should be compared to decide whether a test passes or fails. /// Specifies how two values should be compared to decide whether a test passes or fails.
/// ///
/// Used for both depth testing and stencil testing. /// Used for both depth testing and stencil testing.
#[non_exhaustive]
CompareOp = CompareOp(i32); CompareOp = CompareOp(i32);
/// The test never passes. /// The test never passes.

Some files were not shown because too many files have changed in this diff Show More