diff --git a/examples/src/bin/basic-compute-shader.rs b/examples/src/bin/basic-compute-shader.rs index 5b659a01..c2a82eaf 100644 --- a/examples/src/bin/basic-compute-shader.rs +++ b/examples/src/bin/basic-compute-shader.rs @@ -23,6 +23,7 @@ use vulkano::{ }, device::{ physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, + QueueFlags, }, instance::{Instance, InstanceCreateInfo}, memory::allocator::StandardMemoryAllocator, @@ -58,7 +59,7 @@ fn main() { // that supports compute operations. p.queue_family_properties() .iter() - .position(|q| q.queue_flags.compute) + .position(|q| q.queue_flags.intersects(QueueFlags::COMPUTE)) .map(|i| (p, i as u32)) }) .min_by_key(|(p, _)| match p.properties().device_type { @@ -157,10 +158,7 @@ fn main() { // Builds the buffer and fills it with this iterator. CpuAccessibleBuffer::from_iter( &memory_allocator, - BufferUsage { - storage_buffer: true, - ..BufferUsage::empty() - }, + BufferUsage::STORAGE_BUFFER, false, data_iter, ) diff --git a/examples/src/bin/buffer-pool.rs b/examples/src/bin/buffer-pool.rs index e405c491..40f0137c 100644 --- a/examples/src/bin/buffer-pool.rs +++ b/examples/src/bin/buffer-pool.rs @@ -32,6 +32,7 @@ use vulkano::{ }, device::{ physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, + QueueFlags, }, image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage}, impl_vertex, @@ -99,7 +100,8 @@ fn main() { .iter() .enumerate() .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)) }) @@ -155,13 +157,10 @@ fn main() { min_image_count: surface_capabilities.min_image_count, image_format, image_extent: window.inner_size().into(), - image_usage: ImageUsage { - color_attachment: true, - ..ImageUsage::empty() - }, + image_usage: ImageUsage::COLOR_ATTACHMENT, composite_alpha: surface_capabilities .supported_composite_alpha - .iter() + .into_iter() .next() .unwrap(), ..Default::default() diff --git a/examples/src/bin/clear_attachments.rs b/examples/src/bin/clear_attachments.rs index 48c1cd33..7373c3ae 100644 --- a/examples/src/bin/clear_attachments.rs +++ b/examples/src/bin/clear_attachments.rs @@ -15,6 +15,7 @@ use vulkano::{ }, device::{ physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, + QueueFlags, }, image::{view::ImageView, ImageUsage, SwapchainImage}, instance::{Instance, InstanceCreateInfo}, @@ -68,7 +69,8 @@ fn main() { .iter() .enumerate() .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)) }) @@ -123,13 +125,10 @@ fn main() { min_image_count: surface_capabilities.min_image_count, image_format, image_extent: window.inner_size().into(), - image_usage: ImageUsage { - color_attachment: true, - ..ImageUsage::empty() - }, + image_usage: ImageUsage::COLOR_ATTACHMENT, composite_alpha: surface_capabilities .supported_composite_alpha - .iter() + .into_iter() .next() .unwrap(), ..Default::default() diff --git a/examples/src/bin/debug.rs b/examples/src/bin/debug.rs index 141f5467..2cbedb79 100644 --- a/examples/src/bin/debug.rs +++ b/examples/src/bin/debug.rs @@ -87,37 +87,31 @@ fn main() { DebugUtilsMessenger::new( instance.clone(), DebugUtilsMessengerCreateInfo { - message_severity: DebugUtilsMessageSeverity { - error: true, - warning: true, - information: true, - verbose: true, - ..DebugUtilsMessageSeverity::empty() - }, - message_type: DebugUtilsMessageType { - general: true, - validation: true, - performance: true, - ..DebugUtilsMessageType::empty() - }, + message_severity: DebugUtilsMessageSeverity::ERROR + | DebugUtilsMessageSeverity::WARNING + | DebugUtilsMessageSeverity::INFO + | DebugUtilsMessageSeverity::VERBOSE, + message_type: DebugUtilsMessageType::GENERAL + | DebugUtilsMessageType::VALIDATION + | DebugUtilsMessageType::PERFORMANCE, ..DebugUtilsMessengerCreateInfo::user_callback(Arc::new(|msg| { - let severity = if msg.severity.error { + let severity = if msg.severity.intersects(DebugUtilsMessageSeverity::ERROR) { "error" - } else if msg.severity.warning { + } else if msg.severity.intersects(DebugUtilsMessageSeverity::WARNING) { "warning" - } else if msg.severity.information { + } else if msg.severity.intersects(DebugUtilsMessageSeverity::INFO) { "information" - } else if msg.severity.verbose { + } else if msg.severity.intersects(DebugUtilsMessageSeverity::VERBOSE) { "verbose" } else { panic!("no-impl"); }; - let ty = if msg.ty.general { + let ty = if msg.ty.intersects(DebugUtilsMessageType::GENERAL) { "general" - } else if msg.ty.validation { + } else if msg.ty.intersects(DebugUtilsMessageType::VALIDATION) { "validation" - } else if msg.ty.performance { + } else if msg.ty.intersects(DebugUtilsMessageType::PERFORMANCE) { "performance" } else { panic!("no-impl"); diff --git a/examples/src/bin/deferred/frame/ambient_lighting_system.rs b/examples/src/bin/deferred/frame/ambient_lighting_system.rs index 97b1971b..527ef643 100644 --- a/examples/src/bin/deferred/frame/ambient_lighting_system.rs +++ b/examples/src/bin/deferred/frame/ambient_lighting_system.rs @@ -69,10 +69,7 @@ impl AmbientLightingSystem { let vertex_buffer = { CpuAccessibleBuffer::from_iter( memory_allocator, - BufferUsage { - vertex_buffer: true, - ..BufferUsage::empty() - }, + BufferUsage::VERTEX_BUFFER, false, vertices, ) diff --git a/examples/src/bin/deferred/frame/directional_lighting_system.rs b/examples/src/bin/deferred/frame/directional_lighting_system.rs index 4e246635..56645aaa 100644 --- a/examples/src/bin/deferred/frame/directional_lighting_system.rs +++ b/examples/src/bin/deferred/frame/directional_lighting_system.rs @@ -70,10 +70,7 @@ impl DirectionalLightingSystem { let vertex_buffer = { CpuAccessibleBuffer::from_iter( memory_allocator, - BufferUsage { - vertex_buffer: true, - ..BufferUsage::empty() - }, + BufferUsage::VERTEX_BUFFER, false, vertices, ) diff --git a/examples/src/bin/deferred/frame/point_lighting_system.rs b/examples/src/bin/deferred/frame/point_lighting_system.rs index 32c87688..ad671992 100644 --- a/examples/src/bin/deferred/frame/point_lighting_system.rs +++ b/examples/src/bin/deferred/frame/point_lighting_system.rs @@ -69,10 +69,7 @@ impl PointLightingSystem { let vertex_buffer = { CpuAccessibleBuffer::from_iter( memory_allocator, - BufferUsage { - vertex_buffer: true, - ..BufferUsage::empty() - }, + BufferUsage::VERTEX_BUFFER, false, vertices, ) diff --git a/examples/src/bin/deferred/frame/system.rs b/examples/src/bin/deferred/frame/system.rs index 32478e8d..bbc14149 100644 --- a/examples/src/bin/deferred/frame/system.rs +++ b/examples/src/bin/deferred/frame/system.rs @@ -158,11 +158,7 @@ impl FrameSystem { &memory_allocator, [1, 1], Format::A2B10G10R10_UNORM_PACK32, - ImageUsage { - transient_attachment: true, - input_attachment: true, - ..ImageUsage::empty() - }, + ImageUsage::TRANSIENT_ATTACHMENT | ImageUsage::INPUT_ATTACHMENT, ) .unwrap(), ) @@ -172,11 +168,7 @@ impl FrameSystem { &memory_allocator, [1, 1], Format::R16G16B16A16_SFLOAT, - ImageUsage { - transient_attachment: true, - input_attachment: true, - ..ImageUsage::empty() - }, + ImageUsage::TRANSIENT_ATTACHMENT | ImageUsage::INPUT_ATTACHMENT, ) .unwrap(), ) @@ -186,11 +178,7 @@ impl FrameSystem { &memory_allocator, [1, 1], Format::D16_UNORM, - ImageUsage { - transient_attachment: true, - input_attachment: true, - ..ImageUsage::empty() - }, + ImageUsage::TRANSIENT_ATTACHMENT | ImageUsage::INPUT_ATTACHMENT, ) .unwrap(), ) @@ -280,11 +268,7 @@ impl FrameSystem { &self.memory_allocator, img_dims, Format::A2B10G10R10_UNORM_PACK32, - ImageUsage { - transient_attachment: true, - input_attachment: true, - ..ImageUsage::empty() - }, + ImageUsage::TRANSIENT_ATTACHMENT | ImageUsage::INPUT_ATTACHMENT, ) .unwrap(), ) @@ -294,11 +278,7 @@ impl FrameSystem { &self.memory_allocator, img_dims, Format::R16G16B16A16_SFLOAT, - ImageUsage { - transient_attachment: true, - input_attachment: true, - ..ImageUsage::empty() - }, + ImageUsage::TRANSIENT_ATTACHMENT | ImageUsage::INPUT_ATTACHMENT, ) .unwrap(), ) @@ -308,11 +288,7 @@ impl FrameSystem { &self.memory_allocator, img_dims, Format::D16_UNORM, - ImageUsage { - transient_attachment: true, - input_attachment: true, - ..ImageUsage::empty() - }, + ImageUsage::TRANSIENT_ATTACHMENT | ImageUsage::INPUT_ATTACHMENT, ) .unwrap(), ) diff --git a/examples/src/bin/deferred/main.rs b/examples/src/bin/deferred/main.rs index 8e7d79f8..db856be5 100644 --- a/examples/src/bin/deferred/main.rs +++ b/examples/src/bin/deferred/main.rs @@ -35,6 +35,7 @@ use vulkano::{ command_buffer::allocator::StandardCommandBufferAllocator, device::{ physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, + QueueFlags, }, image::{view::ImageView, ImageUsage}, instance::{Instance, InstanceCreateInfo}, @@ -90,7 +91,8 @@ fn main() { .iter() .enumerate() .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)) }) @@ -145,13 +147,10 @@ fn main() { min_image_count: surface_capabilities.min_image_count, image_format, image_extent: window.inner_size().into(), - image_usage: ImageUsage { - color_attachment: true, - ..ImageUsage::empty() - }, + image_usage: ImageUsage::COLOR_ATTACHMENT, composite_alpha: surface_capabilities .supported_composite_alpha - .iter() + .into_iter() .next() .unwrap(), ..Default::default() diff --git a/examples/src/bin/deferred/triangle_draw_system.rs b/examples/src/bin/deferred/triangle_draw_system.rs index d5dc986d..2b3836b1 100644 --- a/examples/src/bin/deferred/triangle_draw_system.rs +++ b/examples/src/bin/deferred/triangle_draw_system.rs @@ -60,10 +60,7 @@ impl TriangleDrawSystem { let vertex_buffer = { CpuAccessibleBuffer::from_iter( memory_allocator, - BufferUsage { - vertex_buffer: true, - ..BufferUsage::empty() - }, + BufferUsage::VERTEX_BUFFER, false, vertices, ) diff --git a/examples/src/bin/dynamic-buffers.rs b/examples/src/bin/dynamic-buffers.rs index 9a220f19..c56a4799 100644 --- a/examples/src/bin/dynamic-buffers.rs +++ b/examples/src/bin/dynamic-buffers.rs @@ -26,6 +26,7 @@ use vulkano::{ }, device::{ physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, + QueueFlags, }, instance::{Instance, InstanceCreateInfo}, memory::allocator::StandardMemoryAllocator, @@ -57,7 +58,7 @@ fn main() { .filter_map(|p| { p.queue_family_properties() .iter() - .position(|q| q.queue_flags.compute) + .position(|q| q.queue_flags.intersects(QueueFlags::COMPUTE)) .map(|i| (p, i as u32)) }) .min_by_key(|(p, _)| match p.properties().device_type { @@ -168,10 +169,7 @@ fn main() { let input_buffer = CpuAccessibleBuffer::from_iter( &memory_allocator, - BufferUsage { - uniform_buffer: true, - ..BufferUsage::empty() - }, + BufferUsage::UNIFORM_BUFFER, false, aligned_data.into_iter(), ) @@ -179,10 +177,7 @@ fn main() { let output_buffer = CpuAccessibleBuffer::from_iter( &memory_allocator, - BufferUsage { - storage_buffer: true, - ..BufferUsage::empty() - }, + BufferUsage::STORAGE_BUFFER, false, (0..12).map(|_| 0u32), ) diff --git a/examples/src/bin/dynamic-local-size.rs b/examples/src/bin/dynamic-local-size.rs index fdb94878..103edf0b 100644 --- a/examples/src/bin/dynamic-local-size.rs +++ b/examples/src/bin/dynamic-local-size.rs @@ -26,6 +26,7 @@ use vulkano::{ }, device::{ physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, + QueueFlags, }, format::Format, image::{view::ImageView, ImageDimensions, StorageImage}, @@ -65,7 +66,7 @@ fn main() { .filter_map(|p| { p.queue_family_properties() .iter() - .position(|q| q.queue_flags.compute) + .position(|q| q.queue_flags.intersects(QueueFlags::COMPUTE)) .map(|i| (p, i as u32)) }) .min_by_key(|(p, _)| match p.properties().device_type { @@ -227,10 +228,7 @@ fn main() { let buf = CpuAccessibleBuffer::from_iter( &memory_allocator, - BufferUsage { - transfer_dst: true, - ..BufferUsage::empty() - }, + BufferUsage::TRANSFER_DST, false, (0..1024 * 1024 * 4).map(|_| 0u8), ) diff --git a/examples/src/bin/gl-interop.rs b/examples/src/bin/gl-interop.rs index 4ecfa654..8d0b2a96 100644 --- a/examples/src/bin/gl-interop.rs +++ b/examples/src/bin/gl-interop.rs @@ -26,7 +26,7 @@ mod linux { }, device::{ physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, Queue, - QueueCreateInfo, + QueueCreateInfo, QueueFlags, }, format::Format, image::{view::ImageView, ImageCreateFlags, ImageUsage, StorageImage, SwapchainImage}, @@ -107,16 +107,8 @@ mod linux { array_layers: 1, }, Format::R16G16B16A16_UNORM, - ImageUsage { - sampled: true, - transfer_src: true, - transfer_dst: true, - ..ImageUsage::empty() - }, - ImageCreateFlags { - mutable_format: true, - ..ImageCreateFlags::empty() - }, + ImageUsage::SAMPLED | ImageUsage::TRANSFER_SRC | ImageUsage::TRANSFER_DST, + ImageCreateFlags::MUTABLE_FORMAT, [queue.queue_family_index()], ) .unwrap(); @@ -132,10 +124,7 @@ mod linux { Semaphore::new( device.clone(), SemaphoreCreateInfo { - export_handle_types: ExternalSemaphoreHandleTypes { - opaque_fd: true, - ..ExternalSemaphoreHandleTypes::empty() - }, + export_handle_types: ExternalSemaphoreHandleTypes::OPAQUE_FD, ..Default::default() }, ) @@ -145,10 +134,7 @@ mod linux { Semaphore::new( device.clone(), SemaphoreCreateInfo { - export_handle_types: ExternalSemaphoreHandleTypes { - opaque_fd: true, - ..ExternalSemaphoreHandleTypes::empty() - }, + export_handle_types: ExternalSemaphoreHandleTypes::OPAQUE_FD, ..Default::default() }, ) @@ -486,7 +472,7 @@ mod linux { .iter() .enumerate() .position(|(i, q)| { - q.queue_flags.graphics + q.queue_flags.intersects(QueueFlags::GRAPHICS) && p.surface_support(i as u32, &surface).unwrap_or(false) }) .map(|i| (p, i as u32)) @@ -550,13 +536,10 @@ mod linux { min_image_count: surface_capabilities.min_image_count, image_format, image_extent: window.inner_size().into(), - image_usage: ImageUsage { - color_attachment: true, - ..ImageUsage::empty() - }, + image_usage: ImageUsage::COLOR_ATTACHMENT, composite_alpha: surface_capabilities .supported_composite_alpha - .iter() + .into_iter() .next() .unwrap(), ..Default::default() @@ -583,10 +566,7 @@ mod linux { ]; let vertex_buffer = CpuAccessibleBuffer::<[Vertex]>::from_iter( &memory_allocator, - BufferUsage { - vertex_buffer: true, - ..BufferUsage::empty() - }, + BufferUsage::VERTEX_BUFFER, false, vertices, ) diff --git a/examples/src/bin/image-self-copy-blit/main.rs b/examples/src/bin/image-self-copy-blit/main.rs index 6541b755..11b28ef6 100644 --- a/examples/src/bin/image-self-copy-blit/main.rs +++ b/examples/src/bin/image-self-copy-blit/main.rs @@ -22,6 +22,7 @@ use vulkano::{ }, device::{ physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, + QueueFlags, }, format::Format, image::{ @@ -91,7 +92,8 @@ fn main() { .iter() .enumerate() .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)) }) @@ -146,13 +148,10 @@ fn main() { min_image_count: surface_capabilities.min_image_count, image_format, image_extent: window.inner_size().into(), - image_usage: ImageUsage { - color_attachment: true, - ..ImageUsage::empty() - }, + image_usage: ImageUsage::COLOR_ATTACHMENT, composite_alpha: surface_capabilities .supported_composite_alpha - .iter() + .into_iter() .next() .unwrap(), ..Default::default() @@ -186,10 +185,7 @@ fn main() { ]; let vertex_buffer = CpuAccessibleBuffer::<[Vertex]>::from_iter( &memory_allocator, - BufferUsage { - vertex_buffer: true, - ..BufferUsage::empty() - }, + BufferUsage::VERTEX_BUFFER, false, vertices, ) @@ -250,10 +246,7 @@ fn main() { let buffer = CpuAccessibleBuffer::from_iter( &memory_allocator, - BufferUsage { - transfer_src: true, - ..BufferUsage::empty() - }, + BufferUsage::TRANSFER_SRC, false, image_data, ) diff --git a/examples/src/bin/image/main.rs b/examples/src/bin/image/main.rs index 5ea73e88..090452f5 100644 --- a/examples/src/bin/image/main.rs +++ b/examples/src/bin/image/main.rs @@ -20,6 +20,7 @@ use vulkano::{ }, device::{ physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, + QueueFlags, }, format::Format, image::{ @@ -89,7 +90,8 @@ fn main() { .iter() .enumerate() .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)) }) @@ -144,13 +146,10 @@ fn main() { min_image_count: surface_capabilities.min_image_count, image_format, image_extent: window.inner_size().into(), - image_usage: ImageUsage { - color_attachment: true, - ..ImageUsage::empty() - }, + image_usage: ImageUsage::COLOR_ATTACHMENT, composite_alpha: surface_capabilities .supported_composite_alpha - .iter() + .into_iter() .next() .unwrap(), ..Default::default() @@ -184,10 +183,7 @@ fn main() { ]; let vertex_buffer = CpuAccessibleBuffer::<[Vertex]>::from_iter( &memory_allocator, - BufferUsage { - vertex_buffer: true, - ..BufferUsage::empty() - }, + BufferUsage::VERTEX_BUFFER, false, vertices, ) diff --git a/examples/src/bin/immutable-sampler/main.rs b/examples/src/bin/immutable-sampler/main.rs index 777cbb30..3106cbde 100644 --- a/examples/src/bin/immutable-sampler/main.rs +++ b/examples/src/bin/immutable-sampler/main.rs @@ -29,6 +29,7 @@ use vulkano::{ }, device::{ physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, + QueueFlags, }, format::Format, image::{ @@ -95,7 +96,8 @@ fn main() { .iter() .enumerate() .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)) }) @@ -150,13 +152,10 @@ fn main() { min_image_count: surface_capabilities.min_image_count, image_format, image_extent: window.inner_size().into(), - image_usage: ImageUsage { - color_attachment: true, - ..ImageUsage::empty() - }, + image_usage: ImageUsage::COLOR_ATTACHMENT, composite_alpha: surface_capabilities .supported_composite_alpha - .iter() + .into_iter() .next() .unwrap(), ..Default::default() @@ -190,10 +189,7 @@ fn main() { ]; let vertex_buffer = CpuAccessibleBuffer::<[Vertex]>::from_iter( &memory_allocator, - BufferUsage { - vertex_buffer: true, - ..BufferUsage::empty() - }, + BufferUsage::VERTEX_BUFFER, false, vertices, ) diff --git a/examples/src/bin/indirect.rs b/examples/src/bin/indirect.rs index a914617b..cda178c4 100644 --- a/examples/src/bin/indirect.rs +++ b/examples/src/bin/indirect.rs @@ -37,6 +37,7 @@ use vulkano::{ }, device::{ physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, + QueueFlags, }, image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage}, impl_vertex, @@ -108,7 +109,8 @@ fn main() { .iter() .enumerate() .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)) }) @@ -164,13 +166,10 @@ fn main() { min_image_count: surface_capabilities.min_image_count, image_format, image_extent: window.inner_size().into(), - image_usage: ImageUsage { - color_attachment: true, - ..ImageUsage::empty() - }, + image_usage: ImageUsage::COLOR_ATTACHMENT, composite_alpha: surface_capabilities .supported_composite_alpha - .iter() + .into_iter() .next() .unwrap(), ..Default::default() @@ -261,20 +260,12 @@ fn main() { // set the number of vertices to draw let indirect_args_pool: CpuBufferPool = CpuBufferPool::new( memory_allocator.clone(), - BufferUsage { - indirect_buffer: true, - storage_buffer: true, - ..BufferUsage::empty() - }, + BufferUsage::INDIRECT_BUFFER | BufferUsage::STORAGE_BUFFER, MemoryUsage::Upload, ); let vertex_pool: CpuBufferPool = CpuBufferPool::new( memory_allocator, - BufferUsage { - storage_buffer: true, - vertex_buffer: true, - ..BufferUsage::empty() - }, + BufferUsage::STORAGE_BUFFER | BufferUsage::VERTEX_BUFFER, MemoryUsage::Upload, ); diff --git a/examples/src/bin/instancing.rs b/examples/src/bin/instancing.rs index 0b4feb85..8259d0e3 100644 --- a/examples/src/bin/instancing.rs +++ b/examples/src/bin/instancing.rs @@ -22,6 +22,7 @@ use vulkano::{ }, device::{ physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, + QueueFlags, }, image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage}, impl_vertex, @@ -105,7 +106,8 @@ fn main() { .iter() .enumerate() .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)) }) @@ -161,13 +163,10 @@ fn main() { min_image_count: surface_capabilities.min_image_count, image_format, image_extent: window.inner_size().into(), - image_usage: ImageUsage { - color_attachment: true, - ..ImageUsage::empty() - }, + image_usage: ImageUsage::COLOR_ATTACHMENT, composite_alpha: surface_capabilities .supported_composite_alpha - .iter() + .into_iter() .next() .unwrap(), ..Default::default() @@ -194,10 +193,7 @@ fn main() { let vertex_buffer = { CpuAccessibleBuffer::from_iter( &memory_allocator, - BufferUsage { - vertex_buffer: true, - ..BufferUsage::empty() - }, + BufferUsage::VERTEX_BUFFER, false, vertices, ) @@ -229,10 +225,7 @@ fn main() { }; let instance_buffer = CpuAccessibleBuffer::from_iter( &memory_allocator, - BufferUsage { - vertex_buffer: true, - ..BufferUsage::empty() - }, + BufferUsage::VERTEX_BUFFER, false, instances, ) diff --git a/examples/src/bin/interactive_fractal/fractal_compute_pipeline.rs b/examples/src/bin/interactive_fractal/fractal_compute_pipeline.rs index bcbcde46..cb525c49 100644 --- a/examples/src/bin/interactive_fractal/fractal_compute_pipeline.rs +++ b/examples/src/bin/interactive_fractal/fractal_compute_pipeline.rs @@ -57,10 +57,7 @@ impl FractalComputePipeline { let palette_size = colors.len() as i32; let palette = CpuAccessibleBuffer::from_iter( &memory_allocator, - BufferUsage { - storage_buffer: true, - ..BufferUsage::empty() - }, + BufferUsage::STORAGE_BUFFER, false, colors, ) @@ -103,10 +100,7 @@ impl FractalComputePipeline { } self.palette = CpuAccessibleBuffer::from_iter( &self.memory_allocator, - BufferUsage { - storage_buffer: true, - ..BufferUsage::empty() - }, + BufferUsage::STORAGE_BUFFER, false, colors.into_iter(), ) diff --git a/examples/src/bin/interactive_fractal/main.rs b/examples/src/bin/interactive_fractal/main.rs index 71f7bccc..bf9c8517 100644 --- a/examples/src/bin/interactive_fractal/main.rs +++ b/examples/src/bin/interactive_fractal/main.rs @@ -57,13 +57,10 @@ fn main() { primary_window_renderer.add_additional_image_view( render_target_id, DEFAULT_IMAGE_FORMAT, - ImageUsage { - sampled: true, - storage: true, - color_attachment: true, - transfer_dst: true, - ..ImageUsage::empty() - }, + ImageUsage::SAMPLED + | ImageUsage::STORAGE + | ImageUsage::COLOR_ATTACHMENT + | ImageUsage::TRANSFER_DST, ); // Create app to hold the logic of our fractal explorer diff --git a/examples/src/bin/interactive_fractal/pixels_draw_pipeline.rs b/examples/src/bin/interactive_fractal/pixels_draw_pipeline.rs index dee9a355..37a505fa 100644 --- a/examples/src/bin/interactive_fractal/pixels_draw_pipeline.rs +++ b/examples/src/bin/interactive_fractal/pixels_draw_pipeline.rs @@ -89,20 +89,14 @@ impl PixelsDrawPipeline { let (vertices, indices) = textured_quad(2.0, 2.0); let vertex_buffer = CpuAccessibleBuffer::<[TexturedVertex]>::from_iter( memory_allocator, - BufferUsage { - vertex_buffer: true, - ..BufferUsage::empty() - }, + BufferUsage::VERTEX_BUFFER, false, vertices, ) .unwrap(); let index_buffer = CpuAccessibleBuffer::<[u32]>::from_iter( memory_allocator, - BufferUsage { - index_buffer: true, - ..BufferUsage::empty() - }, + BufferUsage::INDEX_BUFFER, false, indices, ) diff --git a/examples/src/bin/msaa-renderpass.rs b/examples/src/bin/msaa-renderpass.rs index bfbe4e06..6498a77d 100644 --- a/examples/src/bin/msaa-renderpass.rs +++ b/examples/src/bin/msaa-renderpass.rs @@ -74,6 +74,7 @@ use vulkano::{ }, device::{ physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, + QueueFlags, }, format::Format, image::{view::ImageView, AttachmentImage, ImageDimensions, SampleCount, StorageImage}, @@ -119,7 +120,7 @@ fn main() { .filter_map(|p| { p.queue_family_properties() .iter() - .position(|q| q.queue_flags.graphics) + .position(|q| q.queue_flags.intersects(QueueFlags::GRAPHICS)) .map(|i| (p, i as u32)) }) .min_by_key(|(p, _)| match p.properties().device_type { @@ -288,10 +289,7 @@ fn main() { ]; let vertex_buffer = CpuAccessibleBuffer::from_iter( &memory_allocator, - BufferUsage { - vertex_buffer: true, - ..BufferUsage::empty() - }, + BufferUsage::VERTEX_BUFFER, false, vertices, ) @@ -321,10 +319,7 @@ fn main() { let buf = CpuAccessibleBuffer::from_iter( &memory_allocator, - BufferUsage { - transfer_dst: true, - ..BufferUsage::empty() - }, + BufferUsage::TRANSFER_DST, false, (0..1024 * 1024 * 4).map(|_| 0u8), ) diff --git a/examples/src/bin/multi-window.rs b/examples/src/bin/multi-window.rs index fe55d872..d87a62e5 100644 --- a/examples/src/bin/multi-window.rs +++ b/examples/src/bin/multi-window.rs @@ -26,6 +26,7 @@ use vulkano::{ }, device::{ physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, + QueueFlags, }, image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage}, impl_vertex, @@ -105,7 +106,7 @@ fn main() { .iter() .enumerate() .position(|(i, q)| { - q.queue_flags.graphics + q.queue_flags.intersects(QueueFlags::GRAPHICS) && p.surface_support(i as u32, &surface).unwrap_or(false) }) .map(|i| (p, i as u32)) @@ -166,13 +167,10 @@ fn main() { min_image_count: surface_caps.min_image_count, image_format, image_extent: window.inner_size().into(), - image_usage: ImageUsage { - color_attachment: true, - ..ImageUsage::empty() - }, + image_usage: ImageUsage::COLOR_ATTACHMENT, composite_alpha: surface_caps .supported_composite_alpha - .iter() + .into_iter() .next() .unwrap(), ..Default::default() @@ -203,10 +201,7 @@ fn main() { ]; let vertex_buffer = CpuAccessibleBuffer::from_iter( &memory_allocator, - BufferUsage { - vertex_buffer: true, - ..BufferUsage::empty() - }, + BufferUsage::VERTEX_BUFFER, false, vertices, ) @@ -329,7 +324,7 @@ fn main() { let (swapchain, images) = { let composite_alpha = surface_caps .supported_composite_alpha - .iter() + .into_iter() .next() .unwrap(); let image_format = Some( @@ -347,10 +342,7 @@ fn main() { min_image_count: surface_caps.min_image_count, image_format, image_extent: window.inner_size().into(), - image_usage: ImageUsage { - color_attachment: true, - ..ImageUsage::empty() - }, + image_usage: ImageUsage::COLOR_ATTACHMENT, composite_alpha, ..Default::default() }, diff --git a/examples/src/bin/multi_window_game_of_life/game_of_life.rs b/examples/src/bin/multi_window_game_of_life/game_of_life.rs index b4a9d145..f99495a8 100644 --- a/examples/src/bin/multi_window_game_of_life/game_of_life.rs +++ b/examples/src/bin/multi_window_game_of_life/game_of_life.rs @@ -47,10 +47,7 @@ fn rand_grid( ) -> Arc> { CpuAccessibleBuffer::from_iter( memory_allocator, - BufferUsage { - storage_buffer: true, - ..BufferUsage::empty() - }, + BufferUsage::STORAGE_BUFFER, false, (0..(size[0] * size[1])) .map(|_| rand::thread_rng().gen_range(0u32..=1)) @@ -87,13 +84,10 @@ impl GameOfLifeComputePipeline { compute_queue.clone(), size, Format::R8G8B8A8_UNORM, - ImageUsage { - sampled: true, - storage: true, - color_attachment: true, - transfer_dst: true, - ..ImageUsage::empty() - }, + ImageUsage::SAMPLED + | ImageUsage::STORAGE + | ImageUsage::COLOR_ATTACHMENT + | ImageUsage::TRANSFER_DST, ) .unwrap(); diff --git a/examples/src/bin/multi_window_game_of_life/pixels_draw.rs b/examples/src/bin/multi_window_game_of_life/pixels_draw.rs index 833dd51c..abd129eb 100644 --- a/examples/src/bin/multi_window_game_of_life/pixels_draw.rs +++ b/examples/src/bin/multi_window_game_of_life/pixels_draw.rs @@ -89,20 +89,14 @@ impl PixelsDrawPipeline { let (vertices, indices) = textured_quad(2.0, 2.0); let vertex_buffer = CpuAccessibleBuffer::<[TexturedVertex]>::from_iter( memory_allocator, - BufferUsage { - vertex_buffer: true, - ..BufferUsage::empty() - }, + BufferUsage::VERTEX_BUFFER, false, vertices.into_iter(), ) .unwrap(); let index_buffer = CpuAccessibleBuffer::<[u32]>::from_iter( memory_allocator, - BufferUsage { - index_buffer: true, - ..BufferUsage::empty() - }, + BufferUsage::INDEX_BUFFER, false, indices.into_iter(), ) diff --git a/examples/src/bin/multiview.rs b/examples/src/bin/multiview.rs index 189bf2ce..3844bdb1 100644 --- a/examples/src/bin/multiview.rs +++ b/examples/src/bin/multiview.rs @@ -23,7 +23,7 @@ use vulkano::{ }, device::{ physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, Features, - QueueCreateInfo, + QueueCreateInfo, QueueFlags, }, format::Format, image::{ @@ -93,7 +93,7 @@ fn main() { .filter_map(|p| { p.queue_family_properties() .iter() - .position(|q| q.queue_flags.graphics) + .position(|q| q.queue_flags.intersects(QueueFlags::GRAPHICS)) .map(|i| (p, i as u32)) }) .min_by_key(|(p, _)| match p.properties().device_type { @@ -140,11 +140,7 @@ fn main() { array_layers: 2, }, Format::B8G8R8A8_SRGB, - ImageUsage { - transfer_src: true, - color_attachment: true, - ..ImageUsage::empty() - }, + ImageUsage::TRANSFER_SRC | ImageUsage::COLOR_ATTACHMENT, ImageCreateFlags::empty(), Some(queue.queue_family_index()), ) @@ -172,10 +168,7 @@ fn main() { ]; let vertex_buffer = CpuAccessibleBuffer::from_iter( &memory_allocator, - BufferUsage { - vertex_buffer: true, - ..BufferUsage::empty() - }, + BufferUsage::VERTEX_BUFFER, false, vertices, ) @@ -286,10 +279,7 @@ fn main() { let create_buffer = || { CpuAccessibleBuffer::from_iter( &memory_allocator, - BufferUsage { - transfer_dst: true, - ..BufferUsage::empty() - }, + BufferUsage::TRANSFER_DST, false, (0..image.dimensions().width() * image.dimensions().height() * 4).map(|_| 0u8), ) diff --git a/examples/src/bin/occlusion-query.rs b/examples/src/bin/occlusion-query.rs index d67cd157..17ed60c6 100644 --- a/examples/src/bin/occlusion-query.rs +++ b/examples/src/bin/occlusion-query.rs @@ -21,6 +21,7 @@ use vulkano::{ }, device::{ physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, + QueueFlags, }, format::Format, image::{view::ImageView, AttachmentImage, ImageAccess, ImageUsage, SwapchainImage}, @@ -84,7 +85,8 @@ fn main() { .iter() .enumerate() .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)) }) @@ -139,13 +141,10 @@ fn main() { min_image_count: surface_capabilities.min_image_count, image_format, image_extent: window.inner_size().into(), - image_usage: ImageUsage { - color_attachment: true, - ..ImageUsage::empty() - }, + image_usage: ImageUsage::COLOR_ATTACHMENT, composite_alpha: surface_capabilities .supported_composite_alpha - .iter() + .into_iter() .next() .unwrap(), ..Default::default() @@ -212,10 +211,7 @@ fn main() { ]; let vertex_buffer = CpuAccessibleBuffer::from_iter( &memory_allocator, - BufferUsage { - vertex_buffer: true, - ..BufferUsage::empty() - }, + BufferUsage::VERTEX_BUFFER, false, vertices, ) @@ -421,15 +417,13 @@ fn main() { ) .unwrap() // Begin query 0, then draw the red triangle. - // Enabling the `precise` bit would give exact numeric results. This needs - // the `occlusion_query_precise` feature to be enabled on the device. + // Enabling the `QueryControlFlags::PRECISE` flag would give exact numeric + // results. This needs the `occlusion_query_precise` feature to be enabled on + // the device. .begin_query( query_pool.clone(), 0, - QueryControlFlags { - precise: false, - ..QueryControlFlags::empty() - }, + QueryControlFlags::empty(), // QueryControlFlags::PRECISE ) .unwrap() .bind_vertex_buffers(0, triangle1.clone()) @@ -439,14 +433,7 @@ fn main() { .end_query(query_pool.clone(), 0) .unwrap() // Begin query 1 for the cyan triangle. - .begin_query( - query_pool.clone(), - 1, - QueryControlFlags { - precise: false, - ..QueryControlFlags::empty() - }, - ) + .begin_query(query_pool.clone(), 1, QueryControlFlags::empty()) .unwrap() .bind_vertex_buffers(0, triangle2.clone()) .draw(triangle2.len() as u32, 1, 0, 0) @@ -454,14 +441,7 @@ fn main() { .end_query(query_pool.clone(), 1) .unwrap() // Finally, query 2 for the green triangle. - .begin_query( - query_pool.clone(), - 2, - QueryControlFlags { - precise: false, - ..QueryControlFlags::empty() - }, - ) + .begin_query(query_pool.clone(), 2, QueryControlFlags::empty()) .unwrap() .bind_vertex_buffers(0, triangle3.clone()) .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 // Vulkano buffer. This could then be used to influence draw operations further down // the line, either in the same frame or a future frame. + #[rustfmt::skip] query_pool .queries_range(0..3) .unwrap() .get_results( &mut query_results, - QueryResultFlags { - // Block the function call until the results are available. - // Note: if not all the queries have actually been executed, then this - // will wait forever for something that never happens! - wait: true, + // Block the function call until the results are available. + // Note: if not all the queries have actually been executed, then this + // will wait forever for something that never happens! + QueryResultFlags::WAIT - // Blocking and waiting will never give partial results. - partial: false, + // Enable this flag to give partial results if available, instead of waiting + // for the full results. + // | QueryResultFlags::PARTIAL - // Blocking and waiting will ensure the results are always available after - // the function returns. - // - // If you disable waiting, then this can be used to include the - // availability of each query's results. You need one extra element per - // query in your `query_results` buffer for this. This element will - // be filled with a zero/nonzero value indicating availability. - with_availability: false, - ..QueryResultFlags::empty() - }, + // Blocking and waiting will ensure the results are always available after + // the function returns. + // + // 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 + // query in your `query_results` buffer for this. This element will + // be filled with a zero/nonzero value indicating availability. + // | QueryResultFlags::WITH_AVAILABILITY ) .unwrap(); @@ -564,11 +543,7 @@ fn window_size_dependent_setup( memory_allocator, dimensions, Format::D16_UNORM, - ImageUsage { - depth_stencil_attachment: true, - transient_attachment: true, - ..ImageUsage::empty() - }, + ImageUsage::DEPTH_STENCIL_ATTACHMENT | ImageUsage::TRANSIENT_ATTACHMENT, ) .unwrap(), ) diff --git a/examples/src/bin/pipeline-caching.rs b/examples/src/bin/pipeline-caching.rs index d9d7b369..b8c41346 100644 --- a/examples/src/bin/pipeline-caching.rs +++ b/examples/src/bin/pipeline-caching.rs @@ -34,6 +34,7 @@ use std::{ use vulkano::{ device::{ physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, + QueueFlags, }, instance::{Instance, InstanceCreateInfo}, pipeline::{cache::PipelineCache, ComputePipeline}, @@ -65,7 +66,7 @@ fn main() { .filter_map(|p| { p.queue_family_properties() .iter() - .position(|q| q.queue_flags.compute) + .position(|q| q.queue_flags.intersects(QueueFlags::COMPUTE)) .map(|i| (p, i as u32)) }) .min_by_key(|(p, _)| match p.properties().device_type { diff --git a/examples/src/bin/push-constants.rs b/examples/src/bin/push-constants.rs index 7a549509..5684b95a 100644 --- a/examples/src/bin/push-constants.rs +++ b/examples/src/bin/push-constants.rs @@ -22,6 +22,7 @@ use vulkano::{ }, device::{ physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, + QueueFlags, }, instance::{Instance, InstanceCreateInfo}, memory::allocator::StandardMemoryAllocator, @@ -53,7 +54,7 @@ fn main() { .filter_map(|p| { p.queue_family_properties() .iter() - .position(|q| q.queue_flags.compute) + .position(|q| q.queue_flags.intersects(QueueFlags::COMPUTE)) .map(|i| (p, i as u32)) }) .min_by_key(|(p, _)| match p.properties().device_type { @@ -139,10 +140,7 @@ fn main() { let data_iter = 0..65536u32; CpuAccessibleBuffer::from_iter( &memory_allocator, - BufferUsage { - storage_buffer: true, - ..BufferUsage::empty() - }, + BufferUsage::STORAGE_BUFFER, false, data_iter, ) diff --git a/examples/src/bin/push-descriptors/main.rs b/examples/src/bin/push-descriptors/main.rs index a97d1100..21af5a69 100644 --- a/examples/src/bin/push-descriptors/main.rs +++ b/examples/src/bin/push-descriptors/main.rs @@ -18,6 +18,7 @@ use vulkano::{ descriptor_set::WriteDescriptorSet, device::{ physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, + QueueFlags, }, format::Format, image::{ @@ -85,7 +86,8 @@ fn main() { .iter() .enumerate() .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)) }) @@ -140,13 +142,10 @@ fn main() { min_image_count: surface_capabilities.min_image_count, image_format, image_extent: window.inner_size().into(), - image_usage: ImageUsage { - color_attachment: true, - ..ImageUsage::empty() - }, + image_usage: ImageUsage::COLOR_ATTACHMENT, composite_alpha: surface_capabilities .supported_composite_alpha - .iter() + .into_iter() .next() .unwrap(), ..Default::default() @@ -180,10 +179,7 @@ fn main() { ]; let vertex_buffer = CpuAccessibleBuffer::<[Vertex]>::from_iter( &memory_allocator, - BufferUsage { - vertex_buffer: true, - ..BufferUsage::empty() - }, + BufferUsage::VERTEX_BUFFER, false, vertices, ) diff --git a/examples/src/bin/runtime-shader/main.rs b/examples/src/bin/runtime-shader/main.rs index 4293d1d6..17b053d0 100644 --- a/examples/src/bin/runtime-shader/main.rs +++ b/examples/src/bin/runtime-shader/main.rs @@ -29,6 +29,7 @@ use vulkano::{ }, device::{ physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, + QueueFlags, }, image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage}, impl_vertex, @@ -100,7 +101,8 @@ fn main() { .iter() .enumerate() .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)) }) @@ -155,13 +157,10 @@ fn main() { min_image_count: surface_capabilities.min_image_count, image_format, image_extent: window.inner_size().into(), - image_usage: ImageUsage { - color_attachment: true, - ..ImageUsage::empty() - }, + image_usage: ImageUsage::COLOR_ATTACHMENT, composite_alpha: surface_capabilities .supported_composite_alpha - .iter() + .into_iter() .next() .unwrap(), ..Default::default() @@ -240,10 +239,7 @@ fn main() { ]; let vertex_buffer = CpuAccessibleBuffer::from_iter( &memory_allocator, - BufferUsage { - vertex_buffer: true, - ..BufferUsage::empty() - }, + BufferUsage::VERTEX_BUFFER, false, vertices, ) diff --git a/examples/src/bin/runtime_array/main.rs b/examples/src/bin/runtime_array/main.rs index 6944b205..6b8666bc 100644 --- a/examples/src/bin/runtime_array/main.rs +++ b/examples/src/bin/runtime_array/main.rs @@ -24,7 +24,7 @@ use vulkano::{ }, device::{ physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, Features, - QueueCreateInfo, + QueueCreateInfo, QueueFlags, }, format::Format, image::{ @@ -94,7 +94,8 @@ fn main() { .iter() .enumerate() .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)) }) @@ -156,13 +157,10 @@ fn main() { min_image_count: surface_capabilities.min_image_count, image_format, image_extent: window.inner_size().into(), - image_usage: ImageUsage { - color_attachment: true, - ..ImageUsage::empty() - }, + image_usage: ImageUsage::COLOR_ATTACHMENT, composite_alpha: surface_capabilities .supported_composite_alpha - .iter() + .into_iter() .next() .unwrap(), ..Default::default() @@ -246,10 +244,7 @@ fn main() { ]; let vertex_buffer = CpuAccessibleBuffer::<[Vertex]>::from_iter( &memory_allocator, - BufferUsage { - vertex_buffer: true, - ..BufferUsage::empty() - }, + BufferUsage::VERTEX_BUFFER, false, vertices, ) diff --git a/examples/src/bin/self-copy-buffer.rs b/examples/src/bin/self-copy-buffer.rs index 4204af38..0b0ae139 100644 --- a/examples/src/bin/self-copy-buffer.rs +++ b/examples/src/bin/self-copy-buffer.rs @@ -21,6 +21,7 @@ use vulkano::{ }, device::{ physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, + QueueFlags, }, instance::{Instance, InstanceCreateInfo}, memory::allocator::StandardMemoryAllocator, @@ -52,7 +53,7 @@ fn main() { .filter_map(|p| { p.queue_family_properties() .iter() - .position(|q| q.queue_flags.compute) + .position(|q| q.queue_flags.intersects(QueueFlags::COMPUTE)) .map(|i| (p, i as u32)) }) .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 }); CpuAccessibleBuffer::from_iter( &memory_allocator, - BufferUsage { - storage_buffer: true, - transfer_src: true, - transfer_dst: true, - ..BufferUsage::empty() - }, + BufferUsage::STORAGE_BUFFER | BufferUsage::TRANSFER_SRC | BufferUsage::TRANSFER_DST, false, data_iter, ) diff --git a/examples/src/bin/shader-include/main.rs b/examples/src/bin/shader-include/main.rs index 22f31239..dcb929c0 100644 --- a/examples/src/bin/shader-include/main.rs +++ b/examples/src/bin/shader-include/main.rs @@ -21,6 +21,7 @@ use vulkano::{ }, device::{ physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, + QueueFlags, }, instance::{Instance, InstanceCreateInfo}, memory::allocator::StandardMemoryAllocator, @@ -52,7 +53,7 @@ fn main() { .filter_map(|p| { p.queue_family_properties() .iter() - .position(|q| q.queue_flags.compute) + .position(|q| q.queue_flags.intersects(QueueFlags::COMPUTE)) .map(|i| (p, i as u32)) }) .min_by_key(|(p, _)| match p.properties().device_type { @@ -134,10 +135,7 @@ fn main() { let data_iter = 0..65536u32; CpuAccessibleBuffer::from_iter( &memory_allocator, - BufferUsage { - storage_buffer: true, - ..BufferUsage::empty() - }, + BufferUsage::STORAGE_BUFFER, false, data_iter, ) diff --git a/examples/src/bin/shader-types-sharing.rs b/examples/src/bin/shader-types-sharing.rs index 44dc14aa..f32f3ef7 100644 --- a/examples/src/bin/shader-types-sharing.rs +++ b/examples/src/bin/shader-types-sharing.rs @@ -38,7 +38,7 @@ use vulkano::{ }, device::{ physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, Queue, - QueueCreateInfo, + QueueCreateInfo, QueueFlags, }, instance::{Instance, InstanceCreateInfo}, memory::allocator::StandardMemoryAllocator, @@ -70,7 +70,7 @@ fn main() { .filter_map(|p| { p.queue_family_properties() .iter() - .position(|q| q.queue_flags.compute) + .position(|q| q.queue_flags.intersects(QueueFlags::COMPUTE)) .map(|i| (p, i as u32)) }) .min_by_key(|(p, _)| match p.properties().device_type { @@ -248,10 +248,7 @@ fn main() { let data_iter = 0..65536u32; CpuAccessibleBuffer::from_iter( &memory_allocator, - BufferUsage { - storage_buffer: true, - ..BufferUsage::empty() - }, + BufferUsage::STORAGE_BUFFER, false, data_iter, ) diff --git a/examples/src/bin/simple-particles.rs b/examples/src/bin/simple-particles.rs index 3b318532..8b3355bd 100644 --- a/examples/src/bin/simple-particles.rs +++ b/examples/src/bin/simple-particles.rs @@ -26,6 +26,7 @@ use vulkano::{ }, device::{ physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, + QueueFlags, }, image::{view::ImageView, ImageUsage}, impl_vertex, @@ -93,7 +94,8 @@ fn main() { .iter() .enumerate() .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)) }) @@ -147,13 +149,10 @@ fn main() { min_image_count: surface_capabilities.min_image_count, image_format, image_extent: [WINDOW_WIDTH as u32, WINDOW_HEIGHT as u32], - image_usage: ImageUsage { - color_attachment: true, - ..ImageUsage::empty() - }, + image_usage: ImageUsage::COLOR_ATTACHMENT, composite_alpha: surface_capabilities .supported_composite_alpha - .iter() + .into_iter() .next() .unwrap(), present_mode: PresentMode::Fifo, @@ -345,10 +344,7 @@ fn main() { // Create a CPU accessible buffer initialized with the vertex data. let temporary_accessible_buffer = CpuAccessibleBuffer::from_iter( &memory_allocator, - BufferUsage { - transfer_src: true, - ..BufferUsage::empty() - }, // Specify this buffer will be used as a transfer source. + BufferUsage::TRANSFER_SRC, // Specify this buffer will be used as a transfer source. false, vertices, ) @@ -358,14 +354,7 @@ fn main() { let device_local_buffer = DeviceLocalBuffer::<[Vertex]>::array( &memory_allocator, PARTICLE_COUNT as vulkano::DeviceSize, - BufferUsage { - 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. + BufferUsage::STORAGE_BUFFER | BufferUsage::TRANSFER_DST | BufferUsage::VERTEX_BUFFER, // Specify use as a storage buffer, vertex buffer, and transfer destination. device.active_queue_family_indices().iter().copied(), ) .unwrap(); diff --git a/examples/src/bin/specialization-constants.rs b/examples/src/bin/specialization-constants.rs index 0930de32..001d54b5 100644 --- a/examples/src/bin/specialization-constants.rs +++ b/examples/src/bin/specialization-constants.rs @@ -19,6 +19,7 @@ use vulkano::{ }, device::{ physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, + QueueFlags, }, instance::{Instance, InstanceCreateInfo}, memory::allocator::StandardMemoryAllocator, @@ -50,7 +51,7 @@ fn main() { .filter_map(|p| { p.queue_family_properties() .iter() - .position(|q| q.queue_flags.compute) + .position(|q| q.queue_flags.intersects(QueueFlags::COMPUTE)) .map(|i| (p, i as u32)) }) .min_by_key(|(p, _)| match p.properties().device_type { @@ -135,10 +136,7 @@ fn main() { let data_iter = 0..65536u32; CpuAccessibleBuffer::from_iter( &memory_allocator, - BufferUsage { - storage_buffer: true, - ..BufferUsage::empty() - }, + BufferUsage::STORAGE_BUFFER, false, data_iter, ) diff --git a/examples/src/bin/teapot/main.rs b/examples/src/bin/teapot/main.rs index f1151b54..a8297666 100644 --- a/examples/src/bin/teapot/main.rs +++ b/examples/src/bin/teapot/main.rs @@ -21,7 +21,7 @@ use vulkano::{ }, device::{ physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, DeviceOwned, - QueueCreateInfo, + QueueCreateInfo, QueueFlags, }, format::Format, image::{view::ImageView, AttachmentImage, ImageAccess, ImageUsage, SwapchainImage}, @@ -87,7 +87,8 @@ fn main() { .iter() .enumerate() .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)) }) @@ -143,13 +144,10 @@ fn main() { min_image_count: surface_capabilities.min_image_count, image_format, image_extent: window.inner_size().into(), - image_usage: ImageUsage { - color_attachment: true, - ..ImageUsage::empty() - }, + image_usage: ImageUsage::COLOR_ATTACHMENT, composite_alpha: surface_capabilities .supported_composite_alpha - .iter() + .into_iter() .next() .unwrap(), ..Default::default() @@ -162,30 +160,21 @@ fn main() { let vertex_buffer = CpuAccessibleBuffer::from_iter( &memory_allocator, - BufferUsage { - vertex_buffer: true, - ..BufferUsage::empty() - }, + BufferUsage::VERTEX_BUFFER, false, VERTICES, ) .unwrap(); let normals_buffer = CpuAccessibleBuffer::from_iter( &memory_allocator, - BufferUsage { - vertex_buffer: true, - ..BufferUsage::empty() - }, + BufferUsage::VERTEX_BUFFER, false, NORMALS, ) .unwrap(); let index_buffer = CpuAccessibleBuffer::from_iter( &memory_allocator, - BufferUsage { - index_buffer: true, - ..BufferUsage::empty() - }, + BufferUsage::INDEX_BUFFER, false, INDICES, ) @@ -193,10 +182,7 @@ fn main() { let uniform_buffer = CpuBufferPool::::new( memory_allocator.clone(), - BufferUsage { - uniform_buffer: true, - ..BufferUsage::empty() - }, + BufferUsage::UNIFORM_BUFFER, MemoryUsage::Upload, ); diff --git a/examples/src/bin/tessellation.rs b/examples/src/bin/tessellation.rs index 672fa083..6dea7568 100644 --- a/examples/src/bin/tessellation.rs +++ b/examples/src/bin/tessellation.rs @@ -28,7 +28,7 @@ use vulkano::{ }, device::{ physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, Features, - QueueCreateInfo, + QueueCreateInfo, QueueFlags, }, image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage}, impl_vertex, @@ -192,7 +192,8 @@ fn main() { .iter() .enumerate() .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)) }) @@ -248,13 +249,10 @@ fn main() { min_image_count: surface_capabilities.min_image_count, image_format, image_extent: window.inner_size().into(), - image_usage: ImageUsage { - color_attachment: true, - ..ImageUsage::empty() - }, + image_usage: ImageUsage::COLOR_ATTACHMENT, composite_alpha: surface_capabilities .supported_composite_alpha - .iter() + .into_iter() .next() .unwrap(), ..Default::default() @@ -303,10 +301,7 @@ fn main() { ]; let vertex_buffer = CpuAccessibleBuffer::from_iter( &memory_allocator, - BufferUsage { - vertex_buffer: true, - ..BufferUsage::empty() - }, + BufferUsage::VERTEX_BUFFER, false, vertices, ) diff --git a/examples/src/bin/texture_array/main.rs b/examples/src/bin/texture_array/main.rs index ec6a62c3..32213606 100644 --- a/examples/src/bin/texture_array/main.rs +++ b/examples/src/bin/texture_array/main.rs @@ -20,6 +20,7 @@ use vulkano::{ }, device::{ physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, + QueueFlags, }, format::Format, image::{ @@ -91,7 +92,8 @@ fn main() { .iter() .enumerate() .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)) }) @@ -146,13 +148,10 @@ fn main() { min_image_count: surface_capabilities.min_image_count, image_format, image_extent: window.inner_size().into(), - image_usage: ImageUsage { - color_attachment: true, - ..ImageUsage::empty() - }, + image_usage: ImageUsage::COLOR_ATTACHMENT, composite_alpha: surface_capabilities .supported_composite_alpha - .iter() + .into_iter() .next() .unwrap(), ..Default::default() @@ -186,10 +185,7 @@ fn main() { ]; let vertex_buffer = CpuAccessibleBuffer::<[Vertex]>::from_iter( &memory_allocator, - BufferUsage { - vertex_buffer: true, - ..BufferUsage::empty() - }, + BufferUsage::VERTEX_BUFFER, false, vertices, ) diff --git a/examples/src/bin/triangle-v1_3.rs b/examples/src/bin/triangle-v1_3.rs index 6a8f205b..3d2e1b94 100644 --- a/examples/src/bin/triangle-v1_3.rs +++ b/examples/src/bin/triangle-v1_3.rs @@ -31,7 +31,7 @@ use vulkano::{ }, device::{ physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, Features, - QueueCreateInfo, + QueueCreateInfo, QueueFlags, }, image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage}, impl_vertex, @@ -142,7 +142,8 @@ fn main() { // 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 // 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 // found, `None` is returned to `filter_map`, which disqualifies this physical @@ -261,16 +262,13 @@ fn main() { // use that. image_extent: window.inner_size().into(), - image_usage: ImageUsage { - color_attachment: true, - ..ImageUsage::empty() - }, + image_usage: ImageUsage::COLOR_ATTACHMENT, // 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. composite_alpha: surface_capabilities .supported_composite_alpha - .iter() + .into_iter() .next() .unwrap(), @@ -305,10 +303,7 @@ fn main() { ]; let vertex_buffer = CpuAccessibleBuffer::from_iter( &memory_allocator, - BufferUsage { - vertex_buffer: true, - ..BufferUsage::empty() - }, + BufferUsage::VERTEX_BUFFER, false, vertices, ) diff --git a/examples/src/bin/triangle.rs b/examples/src/bin/triangle.rs index 7b1bdfc5..90f942a8 100644 --- a/examples/src/bin/triangle.rs +++ b/examples/src/bin/triangle.rs @@ -26,6 +26,7 @@ use vulkano::{ }, device::{ physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, + QueueFlags, }, image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage}, impl_vertex, @@ -131,7 +132,8 @@ fn main() { // 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 // 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 // found, `None` is returned to `filter_map`, which disqualifies this physical @@ -241,16 +243,13 @@ fn main() { // use that. image_extent: window.inner_size().into(), - image_usage: ImageUsage { - color_attachment: true, - ..ImageUsage::empty() - }, + image_usage: ImageUsage::COLOR_ATTACHMENT, // 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. composite_alpha: surface_capabilities .supported_composite_alpha - .iter() + .into_iter() .next() .unwrap(), @@ -285,10 +284,7 @@ fn main() { ]; let vertex_buffer = CpuAccessibleBuffer::from_iter( &memory_allocator, - BufferUsage { - vertex_buffer: true, - ..BufferUsage::empty() - }, + BufferUsage::VERTEX_BUFFER, false, vertices, ) diff --git a/vulkano-shaders/src/entry_point.rs b/vulkano-shaders/src/entry_point.rs index 2852dd70..b30f5898 100644 --- a/vulkano-shaders/src/entry_point.rs +++ b/vulkano-shaders/src/entry_point.rs @@ -165,38 +165,47 @@ fn write_descriptor_requirements( }) }; let stages = { - let ShaderStages { - vertex, - tessellation_control, - tessellation_evaluation, - geometry, - fragment, - compute, - raygen, - any_hit, - closest_hit, - miss, - intersection, - callable, - _ne: _, - } = stages; + let stages_items = [ + stages.intersects(ShaderStages::VERTEX).then(|| quote! { + ::vulkano::shader::ShaderStages::VERTEX + }), + stages.intersects(ShaderStages::TESSELLATION_CONTROL).then(|| quote! { + ::vulkano::shader::ShaderStages::TESSELLATION_CONTROL + }), + 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! { - ::vulkano::shader::ShaderStages { - 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() - } + #(#stages_items)|* } }; let storage_image_atomic = storage_image_atomic.iter(); @@ -243,38 +252,77 @@ fn write_push_constant_requirements( stages, }) => { let stages = { - let ShaderStages { - vertex, - tessellation_control, - tessellation_evaluation, - geometry, - fragment, - compute, - raygen, - any_hit, - closest_hit, - miss, - intersection, - callable, - _ne: _, - } = stages; + let stages_items = [ + stages.intersects(ShaderStages::VERTEX).then(|| { + quote! { + ::vulkano::shader::ShaderStages::VERTEX + } + }), + stages + .intersects(ShaderStages::TESSELLATION_CONTROL) + .then(|| { + quote! { + ::vulkano::shader::ShaderStages::TESSELLATION_CONTROL + } + }), + 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! { - ::vulkano::shader::ShaderStages { - 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() - } + #(#stages_items)|* } }; diff --git a/vulkano-util/src/context.rs b/vulkano-util/src/context.rs index 1992ef58..822faec5 100644 --- a/vulkano-util/src/context.rs +++ b/vulkano-util/src/context.rs @@ -11,7 +11,7 @@ use std::sync::Arc; use vulkano::{ device::{ physical::{PhysicalDevice, PhysicalDeviceType}, - Device, DeviceCreateInfo, DeviceExtensions, Features, Queue, QueueCreateInfo, + Device, DeviceCreateInfo, DeviceExtensions, Features, Queue, QueueCreateInfo, QueueFlags, }, instance::{ debug::{DebugUtilsMessenger, DebugUtilsMessengerCreateInfo}, @@ -199,7 +199,7 @@ impl VulkanoContext { .iter() .enumerate() .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) .expect("Could not find a queue that supports graphics"); // Try finding a separate queue for compute @@ -208,7 +208,9 @@ impl VulkanoContext { .iter() .enumerate() .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); let is_separate_compute_queue = queue_family_compute.is_some(); diff --git a/vulkano-util/src/renderer.rs b/vulkano-util/src/renderer.rs index f11bfb40..328edba5 100644 --- a/vulkano-util/src/renderer.rs +++ b/vulkano-util/src/renderer.rs @@ -124,13 +124,10 @@ impl VulkanoWindowRenderer { min_image_count: surface_capabilities.min_image_count, image_format, image_extent, - image_usage: ImageUsage { - color_attachment: true, - ..ImageUsage::empty() - }, + image_usage: ImageUsage::COLOR_ATTACHMENT, composite_alpha: surface_capabilities .supported_composite_alpha - .iter() + .into_iter() .next() .unwrap(), ..Default::default() @@ -371,7 +368,7 @@ impl VulkanoWindowRenderer { .collect::>(); for i in resizable_views { 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.add_additional_image_view(i, format, usage); } diff --git a/vulkano/autogen/formats.rs b/vulkano/autogen/formats.rs index 51516ed1..a78bf8ed 100644 --- a/vulkano/autogen/formats.rs +++ b/vulkano/autogen/formats.rs @@ -63,78 +63,30 @@ fn formats_output(members: &[FormatMember]) -> TokenStream { let enum_items = members.iter().map(|FormatMember { name, ffi_name, .. }| { quote! { #name = ash::vk::Format::#ffi_name.as_raw(), } }); - let aspects_color_items = members.iter().filter_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( + let aspects_items = members.iter().map( |FormatMember { name, + aspect_color, + aspect_depth, aspect_stencil, - .. - }| { - if *aspect_stencil { - Some(name) - } else { - None - } - }, - ); - let aspects_plane0_items = members.iter().filter_map( - |FormatMember { - name, aspect_plane0, - .. - }| { - if *aspect_plane0 { - Some(name) - } else { - None - } - }, - ); - let aspects_plane1_items = members.iter().filter_map( - |FormatMember { - name, aspect_plane1, - .. - }| { - if *aspect_plane1 { - Some(name) - } else { - None - } - }, - ); - let aspects_plane2_items = members.iter().filter_map( - |FormatMember { - name, aspect_plane2, .. }| { - if *aspect_plane2 { - Some(name) - } else { - None + let aspect_items = [ + aspect_color.then(|| quote! { crate::image::ImageAspects::COLOR }), + aspect_depth.then(|| quote! { crate::image::ImageAspects::DEPTH }), + 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 { /// Returns the aspects that images of this format have. - pub fn aspects(&self) -> ImageAspects { - ImageAspects { - color: !matches!(self, #(Format::#aspects_color_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() + pub fn aspects(self) -> ImageAspects { + match self { + #(#aspects_items)* } } @@ -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 /// [2, 2, 1] respectively, as the red and blue components are shared across multiple /// texels. - pub fn block_extent(&self) -> [u32; 3] { + pub fn block_extent(self) -> [u32; 3] { match self { #(#block_extent_items)* _ => [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 /// 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. - pub fn block_size(&self) -> Option { + pub fn block_size(self) -> Option { match self { #(#block_size_items)* _ => None, @@ -430,7 +376,7 @@ fn formats_output(members: &[FormatMember]) -> TokenStream { /// 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 /// of certain Vulkan operations, such as image copying. - pub fn compatibility(&self) -> FormatCompatibility { + pub fn compatibility(self) -> FormatCompatibility { FormatCompatibility(match self { #(#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 /// 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. - pub fn components(&self) -> [u8; 4] { + pub fn components(self) -> [u8; 4] { match self { #(#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 /// the format does not use compression. - pub fn compression(&self) -> Option { + pub fn compression(self) -> Option { match self { #(#compression_items)* _ => None, @@ -464,7 +410,7 @@ fn formats_output(members: &[FormatMember]) -> TokenStream { /// equivalent regular format of each plane. /// /// For non-planar formats, returns the empty slice. - pub fn planes(&self) -> &'static [Self] { + pub fn planes(self) -> &'static [Self] { match self { #(#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 /// 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 { #(#texels_per_block_items)* _ => 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` /// for depth/stencil formats. - pub fn type_color(&self) -> Option { + pub fn type_color(self) -> Option { match self { #(#type_color_items)* _ => 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` /// color and stencil-only formats. - pub fn type_depth(&self) -> Option { + pub fn type_depth(self) -> Option { match self { #(#type_depth_items)* _ => 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` /// for color and depth-only formats. - pub fn type_stencil(&self) -> Option { + pub fn type_stencil(self) -> Option { match self { #(#type_stencil_items)* _ => 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 /// `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. - pub fn ycbcr_chroma_sampling(&self) -> Option { + pub fn ycbcr_chroma_sampling(self) -> Option { match self { #(#ycbcr_chroma_sampling_items)* _ => None, diff --git a/vulkano/autogen/mod.rs b/vulkano/autogen/mod.rs index d6d55a66..4c67d6c3 100644 --- a/vulkano/autogen/mod.rs +++ b/vulkano/autogen/mod.rs @@ -432,6 +432,7 @@ fn suffix_key(name: &str) -> u32 { 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) { 3 } else if name.ends_with("EXT") { diff --git a/vulkano/autogen/spirv_reqs.rs b/vulkano/autogen/spirv_reqs.rs index ca6f96a8..879a01f5 100644 --- a/vulkano/autogen/spirv_reqs.rs +++ b/vulkano/autogen/spirv_reqs.rs @@ -63,7 +63,7 @@ enum Enable { #[derive(Clone, Debug, PartialEq)] enum PropertyValue { Bool, - BoolMember(Ident), + BoolMember(Vec), } 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 { PropertyValue::Bool => 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" { (PropertyValue::Bool, format!("property `{}`", property_name)) } 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), ) } else { diff --git a/vulkano/src/buffer/cpu_access.rs b/vulkano/src/buffer/cpu_access.rs index 111b6d25..df71c817 100644 --- a/vulkano/src/buffer/cpu_access.rs +++ b/vulkano/src/buffer/cpu_access.rs @@ -578,20 +578,14 @@ mod tests { assert_should_panic!({ CpuAccessibleBuffer::from_data( &memory_allocator, - BufferUsage { - transfer_dst: true, - ..BufferUsage::empty() - }, + BufferUsage::TRANSFER_DST, false, EMPTY, ) .unwrap(); CpuAccessibleBuffer::from_iter( &memory_allocator, - BufferUsage { - transfer_dst: true, - ..BufferUsage::empty() - }, + BufferUsage::TRANSFER_DST, false, EMPTY.into_iter(), ) diff --git a/vulkano/src/buffer/cpu_pool.rs b/vulkano/src/buffer/cpu_pool.rs index cbeaa5bb..7dda5d1d 100644 --- a/vulkano/src/buffer/cpu_pool.rs +++ b/vulkano/src/buffer/cpu_pool.rs @@ -216,14 +216,7 @@ where /// /// - Panics if `T` has zero size. pub fn upload(allocator: Arc) -> CpuBufferPool { - CpuBufferPool::new( - allocator, - BufferUsage { - transfer_src: true, - ..BufferUsage::empty() - }, - MemoryUsage::Upload, - ) + CpuBufferPool::new(allocator, BufferUsage::TRANSFER_SRC, MemoryUsage::Upload) } /// Builds a `CpuBufferPool` meant for simple downloads. @@ -235,14 +228,7 @@ where /// /// - Panics if `T` has zero size. pub fn download(allocator: Arc) -> CpuBufferPool { - CpuBufferPool::new( - allocator, - BufferUsage { - transfer_dst: true, - ..BufferUsage::empty() - }, - MemoryUsage::Download, - ) + CpuBufferPool::new(allocator, BufferUsage::TRANSFER_DST, MemoryUsage::Download) } /// Builds a `CpuBufferPool` meant for usage as a uniform buffer. @@ -254,14 +240,7 @@ where /// /// - Panics if `T` has zero size. pub fn uniform_buffer(allocator: Arc) -> CpuBufferPool { - CpuBufferPool::new( - allocator, - BufferUsage { - uniform_buffer: true, - ..BufferUsage::empty() - }, - MemoryUsage::Upload, - ) + CpuBufferPool::new(allocator, BufferUsage::UNIFORM_BUFFER, MemoryUsage::Upload) } /// Builds a `CpuBufferPool` meant for usage as a vertex buffer. @@ -273,14 +252,7 @@ where /// /// - Panics if `T` has zero size. pub fn vertex_buffer(allocator: Arc) -> CpuBufferPool { - CpuBufferPool::new( - allocator, - BufferUsage { - vertex_buffer: true, - ..BufferUsage::empty() - }, - MemoryUsage::Upload, - ) + CpuBufferPool::new(allocator, BufferUsage::VERTEX_BUFFER, MemoryUsage::Upload) } /// Builds a `CpuBufferPool` meant for usage as a indirect buffer. @@ -292,14 +264,7 @@ where /// /// - Panics if `T` has zero size. pub fn indirect_buffer(allocator: Arc) -> CpuBufferPool { - CpuBufferPool::new( - allocator, - BufferUsage { - indirect_buffer: true, - ..BufferUsage::empty() - }, - MemoryUsage::Upload, - ) + CpuBufferPool::new(allocator, BufferUsage::INDIRECT_BUFFER, MemoryUsage::Upload) } } @@ -538,7 +503,7 @@ where let idx = current_buffer.next_index.load(Ordering::SeqCst); // 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() .physical_device() .properties() @@ -546,7 +511,7 @@ where } else { 1 }; - let align_storage = if self.buffer_usage.storage_buffer { + let align_storage = if self.buffer_usage.intersects(BufferUsage::STORAGE_BUFFER) { self.device() .physical_device() .properties() diff --git a/vulkano/src/buffer/device_local.rs b/vulkano/src/buffer/device_local.rs index ff825bfa..111d9ed3 100644 --- a/vulkano/src/buffer/device_local.rs +++ b/vulkano/src/buffer/device_local.rs @@ -83,7 +83,8 @@ use std::{ /// // Create a CPU accessible buffer initialized with the data. /// let temporary_accessible_buffer = CpuAccessibleBuffer::from_iter( /// &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, /// data, /// ) @@ -93,11 +94,8 @@ use std::{ /// let device_local_buffer = DeviceLocalBuffer::<[f32]>::array( /// &memory_allocator, /// 10_000 as vulkano::DeviceSize, -/// BufferUsage { -/// storage_buffer: true, -/// transfer_dst: true, -/// ..BufferUsage::empty() -/// }, // Specify use as a storage buffer and transfer destination. +/// // Specify use as a storage buffer and transfer destination. +/// BufferUsage::STORAGE_BUFFER | BufferUsage::TRANSFER_DST, /// device.active_queue_family_indices().iter().copied(), /// ) /// .unwrap(); @@ -182,10 +180,7 @@ where { unsafe { // We automatically set `transfer_dst` to true in order to avoid annoying errors. - let actual_usage = BufferUsage { - transfer_dst: true, - ..usage - }; + let actual_usage = usage | BufferUsage::TRANSFER_DST; let buffer = DeviceLocalBuffer::raw( allocator, @@ -229,15 +224,8 @@ where where A: CommandBufferAllocator, { - let source = CpuAccessibleBuffer::from_data( - allocator, - BufferUsage { - transfer_src: true, - ..BufferUsage::empty() - }, - false, - data, - )?; + let source = + CpuAccessibleBuffer::from_data(allocator, BufferUsage::TRANSFER_SRC, false, data)?; DeviceLocalBuffer::from_buffer(allocator, source, usage, command_buffer_builder) } } @@ -267,15 +255,8 @@ where D::IntoIter: ExactSizeIterator, A: CommandBufferAllocator, { - let source = CpuAccessibleBuffer::from_iter( - allocator, - BufferUsage { - transfer_src: true, - ..BufferUsage::empty() - }, - false, - data, - )?; + let source = + CpuAccessibleBuffer::from_iter(allocator, BufferUsage::TRANSFER_SRC, false, data)?; DeviceLocalBuffer::from_buffer(allocator, source, usage, command_buffer_builder) } } @@ -407,10 +388,7 @@ where // VUID-VkMemoryAllocateInfo-pNext-00639 // Guaranteed because we always create a dedicated allocation - let external_memory_handle_types = ExternalMemoryHandleTypes { - opaque_fd: true, - ..ExternalMemoryHandleTypes::empty() - }; + let external_memory_handle_types = ExternalMemoryHandleTypes::OPAQUE_FD; let raw_buffer = RawBuffer::new( allocator.device().clone(), BufferCreateInfo { @@ -570,24 +548,14 @@ mod tests { let buffer = DeviceLocalBuffer::from_data( &memory_allocator, 12u32, - BufferUsage { - transfer_src: true, - ..BufferUsage::empty() - }, + BufferUsage::TRANSFER_SRC, &mut command_buffer_builder, ) .unwrap(); - let destination = CpuAccessibleBuffer::from_data( - &memory_allocator, - BufferUsage { - transfer_dst: true, - ..BufferUsage::empty() - }, - false, - 0, - ) - .unwrap(); + let destination = + CpuAccessibleBuffer::from_data(&memory_allocator, BufferUsage::TRANSFER_DST, false, 0) + .unwrap(); command_buffer_builder .copy_buffer(CopyBufferInfo::buffers(buffer, destination.clone())) @@ -621,20 +589,14 @@ mod tests { let buffer = DeviceLocalBuffer::from_iter( &allocator, (0..512u32).map(|n| n * 2), - BufferUsage { - transfer_src: true, - ..BufferUsage::empty() - }, + BufferUsage::TRANSFER_SRC, &mut command_buffer_builder, ) .unwrap(); let destination = CpuAccessibleBuffer::from_iter( &allocator, - BufferUsage { - transfer_dst: true, - ..BufferUsage::empty() - }, + BufferUsage::TRANSFER_DST, false, (0..512).map(|_| 0u32), ) @@ -676,10 +638,7 @@ mod tests { DeviceLocalBuffer::from_data( &allocator, (), - BufferUsage { - transfer_dst: true, - ..BufferUsage::empty() - }, + BufferUsage::TRANSFER_DST, &mut command_buffer_builder, ) .unwrap(); diff --git a/vulkano/src/buffer/mod.rs b/vulkano/src/buffer/mod.rs index 1bb13a83..76fc3600 100644 --- a/vulkano/src/buffer/mod.rs +++ b/vulkano/src/buffer/mod.rs @@ -106,8 +106,9 @@ mod traits; mod usage; vulkan_bitflags! { - /// Flags to be set when creating a buffer. #[non_exhaustive] + + /// Flags to be set when creating a buffer. BufferCreateFlags = BufferCreateFlags(u32); /* @@ -118,7 +119,7 @@ vulkan_bitflags! { /// /// [`bind_memory`]: sys::RawBuffer::bind_memory /// [`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. /// @@ -127,7 +128,7 @@ vulkan_bitflags! { /// The [`sparse_residency_buffer`] feature must be enabled on the device. /// /// [`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. /// @@ -136,13 +137,13 @@ vulkan_bitflags! { /// The [`sparse_residency_aliased`] feature must be enabled on the device. /// /// [`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 /// protected objects. /// /// The device API version must be at least 1.1. - protected = PROTECTED { + PROTECTED = PROTECTED { 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 /// [`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, device_extensions: [khr_buffer_device_address, ext_buffer_device_address], }, diff --git a/vulkano/src/buffer/sys.rs b/vulkano/src/buffer/sys.rs index 12ab3b0d..4f97eed3 100644 --- a/vulkano/src/buffer/sys.rs +++ b/vulkano/src/buffer/sys.rs @@ -21,7 +21,8 @@ use crate::{ device::{Device, DeviceOwned}, memory::{ allocator::{AllocationCreationError, MemoryAlloc}, - DedicatedTo, ExternalMemoryHandleType, ExternalMemoryHandleTypes, MemoryRequirements, + DedicatedTo, ExternalMemoryHandleType, ExternalMemoryHandleTypes, MemoryAllocateFlags, + MemoryPropertyFlags, MemoryRequirements, }, range_map::RangeMap, sync::{AccessError, CurrentAccess, Sharing}, @@ -126,7 +127,8 @@ impl RawBuffer { // VUID-VkBufferCreateInfo-flags-00916 if sparse_level.sparse_residency && !device.enabled_features().sparse_residency_buffer { 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 { features: &["sparse_residency_buffer"], ..Default::default() @@ -137,7 +139,8 @@ impl RawBuffer { // VUID-VkBufferCreateInfo-flags-00917 if sparse_level.sparse_aliased && !device.enabled_features().sparse_residency_aliased { 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 { features: &["sparse_residency_aliased"], ..Default::default() @@ -302,21 +305,21 @@ impl RawBuffer { // We have to manually enforce some additional requirements for some buffer types. 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, properties.min_texel_buffer_offset_alignment, ); } - if usage.storage_buffer { + if usage.intersects(BufferUsage::STORAGE_BUFFER) { memory_requirements.alignment = align( memory_requirements.alignment, properties.min_storage_buffer_offset_alignment, ); } - if usage.uniform_buffer { + if usage.intersects(BufferUsage::UNIFORM_BUFFER) { memory_requirements.alignment = align( memory_requirements.alignment, properties.min_uniform_buffer_offset_alignment, @@ -479,7 +482,10 @@ impl RawBuffer { } // VUID-VkBindBufferMemoryInfo-None-01899 - if memory_type.property_flags.protected { + if memory_type + .property_flags + .intersects(MemoryPropertyFlags::PROTECTED) + { return Err(BufferError::MemoryProtectedMismatch { buffer_protected: false, memory_protected: true, @@ -490,7 +496,7 @@ impl RawBuffer { if !memory.export_handle_types().is_empty() && !memory .export_handle_types() - .intersects(&self.external_memory_handle_types) + .intersects(self.external_memory_handle_types) { return Err(BufferError::MemoryExternalHandleTypesDisjoint { buffer_handle_types: self.external_memory_handle_types, @@ -501,7 +507,7 @@ impl RawBuffer { if let Some(handle_type) = memory.imported_handle_type() { // VUID-VkBindBufferMemoryInfo-memory-02985 if !ExternalMemoryHandleTypes::from(handle_type) - .intersects(&self.external_memory_handle_types) + .intersects(self.external_memory_handle_types) { return Err(BufferError::MemoryImportedHandleTypeNotEnabled { buffer_handle_types: self.external_memory_handle_types, @@ -512,8 +518,10 @@ impl RawBuffer { // VUID-VkBindBufferMemoryInfo-bufferDeviceAddress-03339 if !self.device.enabled_extensions().ext_buffer_device_address - && self.usage.shader_device_address - && !memory.flags().device_address + && self.usage.intersects(BufferUsage::SHADER_DEVICE_ADDRESS) + && !memory + .flags() + .intersects(MemoryAllocateFlags::DEVICE_ADDRESS) { 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. /// - /// If any of the fields in this value are set, the device must either support API version 1.1 - /// or the [`khr_external_memory`](crate::device::DeviceExtensions::khr_external_memory) - /// extension must be enabled. + /// If this value is not empty, then the device API version must be at least 1.1, or the + /// [`khr_external_memory`] extension must be enabled on the device. /// /// The default value is [`ExternalMemoryHandleTypes::empty()`]. + /// + /// [`khr_external_memory`]: crate::device::DeviceExtensions::khr_external_memory pub external_memory_handle_types: ExternalMemoryHandleTypes, pub _ne: crate::NonExhaustive, @@ -1429,10 +1438,7 @@ mod tests { device.clone(), BufferCreateInfo { size: 128, - usage: BufferUsage { - transfer_dst: true, - ..BufferUsage::empty() - }, + usage: BufferUsage::TRANSFER_DST, ..Default::default() }, ) @@ -1453,10 +1459,7 @@ mod tests { BufferCreateInfo { size: 128, sparse: Some(BufferCreateFlags::empty()), - usage: BufferUsage { - transfer_dst: true, - ..BufferUsage::empty() - }, + usage: BufferUsage::transfer_dst, ..Default::default() }, ) { @@ -1480,10 +1483,7 @@ mod tests { sparse_aliased: false, ..Default::default() }), - usage: BufferUsage { - transfer_dst: true, - ..BufferUsage::empty() - }, + usage: BufferUsage::transfer_dst, ..Default::default() }, ) { @@ -1507,10 +1507,7 @@ mod tests { sparse_aliased: true, ..Default::default() }), - usage: BufferUsage { - transfer_dst: true, - ..BufferUsage::empty() - }, + usage: BufferUsage::transfer_dst, ..Default::default() }, ) { @@ -1532,10 +1529,7 @@ mod tests { device, BufferCreateInfo { size: 0, - usage: BufferUsage { - transfer_dst: true, - ..BufferUsage::empty() - }, + usage: BufferUsage::TRANSFER_DST, ..Default::default() }, ) diff --git a/vulkano/src/buffer/traits.rs b/vulkano/src/buffer/traits.rs index 1f868629..6eaff9fd 100644 --- a/vulkano/src/buffer/traits.rs +++ b/vulkano/src/buffer/traits.rs @@ -81,7 +81,7 @@ pub unsafe trait BufferAccess: DeviceOwned + Send + Sync { // VUID-vkGetBufferDeviceAddress-bufferDeviceAddress-03324 if !device.enabled_features().buffer_device_address { return Err(BufferDeviceAddressError::RequirementNotMet { - required_for: "`raw_device_address`", + required_for: "`BufferAccess::raw_device_address`", requires_one_of: RequiresOneOf { features: &["buffer_device_address"], ..Default::default() @@ -90,7 +90,11 @@ pub unsafe trait BufferAccess: DeviceOwned + Send + Sync { } // VUID-VkBufferDeviceAddressInfo-buffer-02601 - if !inner.buffer.usage().shader_device_address { + if !inner + .buffer + .usage() + .intersects(BufferUsage::SHADER_DEVICE_ADDRESS) + { return Err(BufferDeviceAddressError::BufferMissingUsage); } diff --git a/vulkano/src/buffer/usage.rs b/vulkano/src/buffer/usage.rs index 8ac9793d..80c42c1d 100644 --- a/vulkano/src/buffer/usage.rs +++ b/vulkano/src/buffer/usage.rs @@ -10,100 +10,101 @@ use crate::macros::vulkan_bitflags; vulkan_bitflags! { + #[non_exhaustive] + /// 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. - #[non_exhaustive] BufferUsage = BufferUsageFlags(u32); /// 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. - transfer_dst = TRANSFER_DST, + TRANSFER_DST = TRANSFER_DST, /// 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. - 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. - uniform_buffer = UNIFORM_BUFFER, + UNIFORM_BUFFER = UNIFORM_BUFFER, /// 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. - index_buffer = INDEX_BUFFER, + INDEX_BUFFER = INDEX_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. - indirect_buffer = INDIRECT_BUFFER, + INDIRECT_BUFFER = INDIRECT_BUFFER, /// The buffer's device address can be retrieved. /// /// 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 - /// on the device. + /// [`MemoryAllocateFlags::DEVICE_ADDRESS`] flag, unless the [`ext_buffer_device_address`] + /// 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 - shader_device_address = SHADER_DEVICE_ADDRESS { + SHADER_DEVICE_ADDRESS = SHADER_DEVICE_ADDRESS { api_version: V1_2, device_extensions: [khr_buffer_device_address, ext_buffer_device_address], }, /* // TODO: document - video_decode_src = VIDEO_DECODE_SRC_KHR { + VIDEO_DECODE_SRC = VIDEO_DECODE_SRC_KHR { device_extensions: [khr_video_decode_queue], }, // TODO: document - video_decode_dst = VIDEO_DECODE_DST_KHR { + VIDEO_DECODE_DST = VIDEO_DECODE_DST_KHR { device_extensions: [khr_video_decode_queue], }, // TODO: document - transform_feedback_buffer = TRANSFORM_FEEDBACK_BUFFER_EXT { + TRANSFORM_FEEDBACK_BUFFER = TRANSFORM_FEEDBACK_BUFFER_EXT { device_extensions: [ext_transform_feedback], }, // 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], }, // TODO: document - conditional_rendering = CONDITIONAL_RENDERING_EXT { + CONDITIONAL_RENDERING = CONDITIONAL_RENDERING_EXT { device_extensions: [ext_conditional_rendering], }, // 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], }, // TODO: document - acceleration_structure_storage = ACCELERATION_STRUCTURE_STORAGE_KHR { + ACCELERATION_STRUCTURE_STORAGE = ACCELERATION_STRUCTURE_STORAGE_KHR { device_extensions: [khr_acceleration_structure], }, // 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], }, // TODO: document - video_encode_dst = VIDEO_ENCODE_DST_KHR { + VIDEO_ENCODE_DST = VIDEO_ENCODE_DST_KHR { device_extensions: [khr_video_encode_queue], }, // TODO: document - video_encode_src = VIDEO_ENCODE_SRC_KHR { + VIDEO_ENCODE_SRC = VIDEO_ENCODE_SRC_KHR { device_extensions: [khr_video_encode_queue], }, */ diff --git a/vulkano/src/buffer/view.rs b/vulkano/src/buffer/view.rs index 405c707c..b74b395b 100644 --- a/vulkano/src/buffer/view.rs +++ b/vulkano/src/buffer/view.rs @@ -26,15 +26,10 @@ //! //! # let queue: Arc = return; //! # let memory_allocator: vulkano::memory::allocator::StandardMemoryAllocator = return; -//! let usage = BufferUsage { -//! storage_texel_buffer: true, -//! ..BufferUsage::empty() -//! }; -//! //! let buffer = DeviceLocalBuffer::<[u32]>::array( //! &memory_allocator, //! 128, -//! usage, +//! BufferUsage::STORAGE_TEXEL_BUFFER, //! [queue.queue_family_index()], //! ) //! .unwrap(); @@ -48,7 +43,7 @@ //! .unwrap(); //! ``` -use super::{BufferAccess, BufferAccessObject, BufferInner}; +use super::{BufferAccess, BufferAccessObject, BufferInner, BufferUsage}; use crate::{ device::{Device, DeviceOwned}, format::{Format, FormatFeatures}, @@ -107,7 +102,9 @@ where format.validate_device(device)?; // 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); } @@ -121,12 +118,20 @@ where }; // 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); } // 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); } @@ -156,7 +161,10 @@ where block_size }; - if inner_buffer.usage().storage_texel_buffer { + if inner_buffer + .usage() + .intersects(BufferUsage::STORAGE_TEXEL_BUFFER) + { let mut required_alignment = properties .storage_texel_buffer_offset_alignment_bytes .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 .uniform_texel_buffer_offset_alignment_bytes .unwrap(); @@ -416,7 +427,7 @@ pub unsafe trait BufferViewAbstract: fn format(&self) -> Option; /// 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. fn range(&self) -> Range; @@ -435,8 +446,8 @@ where self.format } - fn format_features(&self) -> &FormatFeatures { - &self.format_features + fn format_features(&self) -> FormatFeatures { + self.format_features } fn range(&self) -> Range { @@ -475,10 +486,7 @@ mod tests { let (device, queue) = gfx_dev_and_queue!(); let memory_allocator = StandardMemoryAllocator::new_default(device); - let usage = BufferUsage { - uniform_texel_buffer: true, - ..BufferUsage::empty() - }; + let usage = BufferUsage::UNIFORM_TEXEL_BUFFER; let buffer = DeviceLocalBuffer::<[[u8; 4]]>::array( &memory_allocator, @@ -503,10 +511,7 @@ mod tests { let (device, queue) = gfx_dev_and_queue!(); let memory_allocator = StandardMemoryAllocator::new_default(device); - let usage = BufferUsage { - storage_texel_buffer: true, - ..BufferUsage::empty() - }; + let usage = BufferUsage::STORAGE_TEXEL_BUFFER; let buffer = DeviceLocalBuffer::<[[u8; 4]]>::array( &memory_allocator, @@ -531,10 +536,7 @@ mod tests { let (device, queue) = gfx_dev_and_queue!(); let memory_allocator = StandardMemoryAllocator::new_default(device); - let usage = BufferUsage { - storage_texel_buffer: true, - ..BufferUsage::empty() - }; + let usage = BufferUsage::STORAGE_TEXEL_BUFFER; let buffer = DeviceLocalBuffer::<[u32]>::array( &memory_allocator, @@ -562,10 +564,7 @@ mod tests { let buffer = DeviceLocalBuffer::<[[u8; 4]]>::array( &memory_allocator, 128, - BufferUsage { - transfer_dst: true, // Dummy value - ..BufferUsage::empty() - }, + BufferUsage::TRANSFER_DST, // Dummy value [queue.queue_family_index()], ) .unwrap(); @@ -587,11 +586,7 @@ mod tests { let (device, queue) = gfx_dev_and_queue!(); let memory_allocator = StandardMemoryAllocator::new_default(device); - let usage = BufferUsage { - uniform_texel_buffer: true, - storage_texel_buffer: true, - ..BufferUsage::empty() - }; + let usage = BufferUsage::UNIFORM_TEXEL_BUFFER | BufferUsage::STORAGE_TEXEL_BUFFER; let buffer = DeviceLocalBuffer::<[[f64; 4]]>::array( &memory_allocator, diff --git a/vulkano/src/command_buffer/auto.rs b/vulkano/src/command_buffer/auto.rs index ada9427a..665060ba 100644 --- a/vulkano/src/command_buffer/auto.rs +++ b/vulkano/src/command_buffer/auto.rs @@ -23,8 +23,8 @@ use crate::{ buffer::{sys::Buffer, BufferAccess}, command_buffer::CommandBufferInheritanceRenderingInfo, device::{Device, DeviceOwned, Queue, QueueFamilyProperties}, - format::Format, - image::{sys::Image, ImageAccess, ImageLayout, ImageSubresourceRange}, + format::{Format, FormatFeatures}, + image::{sys::Image, ImageAccess, ImageAspects, ImageLayout, ImageSubresourceRange}, query::{QueryControlFlags, QueryType}, render_pass::{Framebuffer, Subpass}, sync::{AccessCheckError, AccessFlags, PipelineMemoryAccess, PipelineStages}, @@ -350,7 +350,9 @@ where // VUID-VkCommandBufferInheritanceRenderingInfo-multiview-06008 if view_mask != 0 && !device.enabled_features().multiview { 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 { features: &["multiview"], ..Default::default() @@ -382,7 +384,7 @@ where // Use unchecked, because all validation has been done above. if !unsafe { physical_device.format_properties_unchecked(format) } .potential_format_features() - .color_attachment + .intersects(FormatFeatures::COLOR_ATTACHMENT) { return Err( CommandBufferBeginError::ColorAttachmentFormatUsageNotSupported { @@ -397,7 +399,7 @@ where format.validate_device(device)?; // VUID-VkCommandBufferInheritanceRenderingInfo-depthAttachmentFormat-06540 - if !format.aspects().depth { + if !format.aspects().intersects(ImageAspects::DEPTH) { return Err( CommandBufferBeginError::DepthAttachmentFormatUsageNotSupported, ); @@ -407,7 +409,7 @@ where // Use unchecked, because all validation has been done above. if !unsafe { physical_device.format_properties_unchecked(format) } .potential_format_features() - .depth_stencil_attachment + .intersects(FormatFeatures::DEPTH_STENCIL_ATTACHMENT) { return Err( CommandBufferBeginError::DepthAttachmentFormatUsageNotSupported, @@ -420,7 +422,7 @@ where format.validate_device(device)?; // VUID-VkCommandBufferInheritanceRenderingInfo-stencilAttachmentFormat-06541 - if !format.aspects().stencil { + if !format.aspects().intersects(ImageAspects::STENCIL) { return Err( CommandBufferBeginError::StencilAttachmentFormatUsageNotSupported, ); @@ -430,7 +432,7 @@ where // Use unchecked, because all validation has been done above. if !unsafe { physical_device.format_properties_unchecked(format) } .potential_format_features() - .depth_stencil_attachment + .intersects(FormatFeatures::DEPTH_STENCIL_ATTACHMENT) { return Err( CommandBufferBeginError::StencilAttachmentFormatUsageNotSupported, @@ -472,10 +474,13 @@ where } // 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 { - required_for: - "`inheritance_info.occlusion_query` is `Some(control_flags)`, where `control_flags.precise` is set", + required_for: "`inheritance_info.occlusion_query` is \ + `Some(control_flags)`, where `control_flags` contains \ + `QueryControlFlags::PRECISE`", requires_one_of: RequiresOneOf { features: &["occlusion_query_precise"], ..Default::default() @@ -948,10 +953,7 @@ mod tests { let source = CpuAccessibleBuffer::from_iter( &memory_allocator, - BufferUsage { - transfer_src: true, - ..BufferUsage::empty() - }, + BufferUsage::TRANSFER_SRC, true, [1_u32, 2].iter().copied(), ) @@ -959,10 +961,7 @@ mod tests { let destination = CpuAccessibleBuffer::from_iter( &memory_allocator, - BufferUsage { - transfer_dst: true, - ..BufferUsage::empty() - }, + BufferUsage::TRANSFER_DST, true, [0_u32, 10, 20, 3, 4].iter().copied(), ) @@ -1083,11 +1082,7 @@ mod tests { let memory_allocator = StandardMemoryAllocator::new_default(device.clone()); let source = CpuAccessibleBuffer::from_iter( &memory_allocator, - BufferUsage { - transfer_src: true, - transfer_dst: true, - ..BufferUsage::empty() - }, + BufferUsage::TRANSFER_SRC | BufferUsage::TRANSFER_DST, true, [0_u32, 1, 2, 3].iter().copied(), ) @@ -1135,11 +1130,7 @@ mod tests { let memory_allocator = StandardMemoryAllocator::new_default(device.clone()); let source = CpuAccessibleBuffer::from_iter( &memory_allocator, - BufferUsage { - transfer_src: true, - transfer_dst: true, - ..BufferUsage::empty() - }, + BufferUsage::TRANSFER_SRC | BufferUsage::TRANSFER_DST, true, [0_u32, 1, 2, 3].iter().copied(), ) diff --git a/vulkano/src/command_buffer/commands/bind_push.rs b/vulkano/src/command_buffer/commands/bind_push.rs index 4cca2bd1..c57cf874 100644 --- a/vulkano/src/command_buffer/commands/bind_push.rs +++ b/vulkano/src/command_buffer/commands/bind_push.rs @@ -8,7 +8,7 @@ // according to those terms. use crate::{ - buffer::{BufferAccess, BufferContents, TypedBufferAccess}, + buffer::{BufferAccess, BufferContents, BufferUsage, TypedBufferAccess}, command_buffer::{ allocator::CommandBufferAllocator, auto::RenderPassStateType, @@ -21,7 +21,7 @@ use crate::{ DescriptorSetUpdateError, DescriptorSetWithOffsets, DescriptorSetsCollection, DescriptorWriteInfo, WriteDescriptorSet, }, - device::DeviceOwned, + device::{DeviceOwned, QueueFlags}, pipeline::{ graphics::{ input_assembly::{Index, IndexType}, @@ -104,12 +104,18 @@ where // VUID-vkCmdBindDescriptorSets-pipelineBindPoint-00361 match pipeline_bind_point { PipelineBindPoint::Compute => { - if !queue_family_properties.queue_flags.compute { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::COMPUTE) + { return Err(BindPushError::NotSupportedByQueueFamily); } } PipelineBindPoint::Graphics => { - if !queue_family_properties.queue_flags.graphics { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS) + { 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 `self` and `index_buffer` do not belong to the same device. - /// - Panics if `index_buffer` does not have the - /// [`index_buffer`](crate::buffer::BufferUsage::index_buffer) usage enabled. - /// - If the index buffer contains `u8` indices, panics if the - /// [`index_type_uint8`](crate::device::Features::index_type_uint8) feature is not - /// enabled on the device. + /// - Panics if `index_buffer` does not have the [`BufferUsage::INDEX_BUFFER`] usage enabled. + /// - If the index buffer contains `u8` indices, panics if the [`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(&mut self, index_buffer: Arc) -> &mut Self where Ib: TypedBufferAccess + 'static, @@ -180,7 +187,10 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdBindIndexBuffer-commandBuffer-cmdpool - if !queue_family_properties.queue_flags.graphics { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS) + { return Err(BindPushError::NotSupportedByQueueFamily); } @@ -188,7 +198,7 @@ where assert_eq!(self.device(), index_buffer.device()); // VUID-vkCmdBindIndexBuffer-buffer-00433 - if !index_buffer.usage().index_buffer { + if !index_buffer.usage().intersects(BufferUsage::INDEX_BUFFER) { return Err(BindPushError::IndexBufferMissingUsage); } @@ -232,7 +242,10 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdBindPipeline-pipelineBindPoint-00777 - if !queue_family_properties.queue_flags.compute { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::COMPUTE) + { return Err(BindPushError::NotSupportedByQueueFamily); } @@ -265,7 +278,10 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdBindPipeline-pipelineBindPoint-00778 - if !queue_family_properties.queue_flags.graphics { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS) + { 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 highest vertex buffer binding being bound is greater than the - /// [`max_vertex_input_bindings`](crate::device::Properties::max_vertex_input_bindings) - // device property. + /// [`max_vertex_input_bindings`] device property. /// - 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 - /// [`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( &mut self, first_binding: u32, @@ -355,7 +373,10 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdBindVertexBuffers-commandBuffer-cmdpool - if !queue_family_properties.queue_flags.graphics { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS) + { return Err(BindPushError::NotSupportedByQueueFamily); } @@ -383,7 +404,7 @@ where assert_eq!(self.device(), buffer.device()); // VUID-vkCmdBindVertexBuffers-pBuffers-00627 - if !buffer.usage().vertex_buffer { + if !buffer.usage().intersects(BufferUsage::VERTEX_BUFFER) { return Err(BindPushError::VertexBufferMissingUsage); } } @@ -554,7 +575,7 @@ where ) -> Result<(), BindPushError> { if !self.device().enabled_extensions().khr_push_descriptor { return Err(BindPushError::RequirementNotMet { - required_for: "`push_descriptor_set`", + required_for: "`AutoCommandBufferBuilder::push_descriptor_set`", requires_one_of: RequiresOneOf { device_extensions: &["khr_push_descriptor"], ..Default::default() @@ -571,12 +592,18 @@ where // VUID-vkCmdPushDescriptorSetKHR-pipelineBindPoint-00363 match pipeline_bind_point { PipelineBindPoint::Compute => { - if !queue_family_properties.queue_flags.compute { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::COMPUTE) + { return Err(BindPushError::NotSupportedByQueueFamily); } } PipelineBindPoint::Graphics => { - if !queue_family_properties.queue_flags.graphics { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS) + { return Err(BindPushError::NotSupportedByQueueFamily); } } @@ -999,7 +1026,7 @@ impl UnsafeCommandBufferBuilder { let inner = buffer.inner(); 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)( self.handle, @@ -1184,7 +1211,7 @@ impl UnsafeCommandBufferBuilderBindVertexBuffer { #[inline] pub fn add(&mut self, buffer: &dyn BufferAccess) { 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.offsets.push(inner.offset); } diff --git a/vulkano/src/command_buffer/commands/debug.rs b/vulkano/src/command_buffer/commands/debug.rs index f48e588f..4d77a4ef 100644 --- a/vulkano/src/command_buffer/commands/debug.rs +++ b/vulkano/src/command_buffer/commands/debug.rs @@ -14,7 +14,7 @@ use crate::{ sys::UnsafeCommandBufferBuilder, AutoCommandBufferBuilder, }, - device::DeviceOwned, + device::{DeviceOwned, QueueFlags}, instance::debug::DebugUtilsLabel, RequiresOneOf, }; @@ -26,9 +26,9 @@ use std::{ /// # Commands for debugging. /// -/// These commands all require the -/// [`ext_debug_utils`](crate::instance::InstanceExtensions::ext_debug_utils) to be enabled on the -/// instance. +/// These commands all require the [`ext_debug_utils`] extension to be enabled on the instance. +/// +/// [`ext_debug_utils`]: crate::instance::InstanceExtensions::ext_debug_utils impl AutoCommandBufferBuilder where A: CommandBufferAllocator, @@ -58,7 +58,7 @@ where .ext_debug_utils { return Err(DebugUtilsError::RequirementNotMet { - required_for: "`begin_debug_utils_label`", + required_for: "`AutoCommandBufferBuilder::begin_debug_utils_label`", requires_one_of: RequiresOneOf { instance_extensions: &["ext_debug_utils"], ..Default::default() @@ -69,8 +69,9 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdBeginDebugUtilsLabelEXT-commandBuffer-cmdpool - if !(queue_family_properties.queue_flags.graphics - || queue_family_properties.queue_flags.compute) + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS | QueueFlags::COMPUTE) { return Err(DebugUtilsError::NotSupportedByQueueFamily); } @@ -101,7 +102,7 @@ where .ext_debug_utils { return Err(DebugUtilsError::RequirementNotMet { - required_for: "`end_debug_utils_label`", + required_for: "`AutoCommandBufferBuilder::end_debug_utils_label`", requires_one_of: RequiresOneOf { instance_extensions: &["ext_debug_utils"], ..Default::default() @@ -112,8 +113,9 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdEndDebugUtilsLabelEXT-commandBuffer-cmdpool - if !(queue_family_properties.queue_flags.graphics - || queue_family_properties.queue_flags.compute) + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS | QueueFlags::COMPUTE) { return Err(DebugUtilsError::NotSupportedByQueueFamily); } @@ -152,7 +154,7 @@ where .ext_debug_utils { return Err(DebugUtilsError::RequirementNotMet { - required_for: "`insert_debug_utils_label`", + required_for: "`AutoCommandBufferBuilder::insert_debug_utils_label`", requires_one_of: RequiresOneOf { instance_extensions: &["ext_debug_utils"], ..Default::default() @@ -163,8 +165,9 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdInsertDebugUtilsLabelEXT-commandBuffer-cmdpool - if !(queue_family_properties.queue_flags.graphics - || queue_family_properties.queue_flags.compute) + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS | QueueFlags::COMPUTE) { return Err(DebugUtilsError::NotSupportedByQueueFamily); } diff --git a/vulkano/src/command_buffer/commands/dynamic_state.rs b/vulkano/src/command_buffer/commands/dynamic_state.rs index 58e58711..31304220 100644 --- a/vulkano/src/command_buffer/commands/dynamic_state.rs +++ b/vulkano/src/command_buffer/commands/dynamic_state.rs @@ -14,7 +14,7 @@ use crate::{ sys::UnsafeCommandBufferBuilder, AutoCommandBufferBuilder, }, - device::DeviceOwned, + device::{DeviceOwned, QueueFlags}, pipeline::{ graphics::{ color_blend::LogicOp, @@ -82,7 +82,10 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdSetBlendConstants-commandBuffer-cmdpool - if !queue_family_properties.queue_flags.graphics { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS) + { return Err(SetDynamicStateError::NotSupportedByQueueFamily); } @@ -125,14 +128,17 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdSetColorWriteEnableEXT-commandBuffer-cmdpool - if !queue_family_properties.queue_flags.graphics { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS) + { return Err(SetDynamicStateError::NotSupportedByQueueFamily); } // VUID-vkCmdSetColorWriteEnableEXT-None-04803 if !self.device().enabled_features().color_write_enable { return Err(SetDynamicStateError::RequirementNotMet { - required_for: "`set_color_write_enable`", + required_for: "`AutoCommandBufferBuilder::set_color_write_enable`", requires_one_of: RequiresOneOf { device_extensions: &["ext_color_write_enable"], ..Default::default() @@ -188,7 +194,10 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdSetCullMode-commandBuffer-cmdpool - if !queue_family_properties.queue_flags.graphics { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS) + { return Err(SetDynamicStateError::NotSupportedByQueueFamily); } @@ -197,7 +206,7 @@ where || self.device().enabled_features().extended_dynamic_state) { return Err(SetDynamicStateError::RequirementNotMet { - required_for: "`set_cull_mode`", + required_for: "`AutoCommandBufferBuilder::set_cull_mode`", requires_one_of: RequiresOneOf { api_version: Some(Version::V1_3), features: &["extended_dynamic_state"], @@ -245,7 +254,10 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdSetDepthBias-commandBuffer-cmdpool - if !queue_family_properties.queue_flags.graphics { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS) + { return Err(SetDynamicStateError::NotSupportedByQueueFamily); } @@ -288,7 +300,10 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdSetDepthBiasEnable-commandBuffer-cmdpool - if !queue_family_properties.queue_flags.graphics { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS) + { return Err(SetDynamicStateError::NotSupportedByQueueFamily); } @@ -297,7 +312,7 @@ where || self.device().enabled_features().extended_dynamic_state2) { return Err(SetDynamicStateError::RequirementNotMet { - required_for: "`set_depth_bias_enable`", + required_for: "`AutoCommandBufferBuilder::set_depth_bias_enable`", requires_one_of: RequiresOneOf { api_version: Some(Version::V1_3), features: &["extended_dynamic_state2"], @@ -338,7 +353,10 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdSetDepthBounds-commandBuffer-cmdpool - if !queue_family_properties.queue_flags.graphics { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS) + { return Err(SetDynamicStateError::NotSupportedByQueueFamily); } @@ -390,7 +408,10 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdSetDepthBoundsTestEnable-commandBuffer-cmdpool - if !queue_family_properties.queue_flags.graphics { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS) + { return Err(SetDynamicStateError::NotSupportedByQueueFamily); } @@ -399,7 +420,7 @@ where || self.device().enabled_features().extended_dynamic_state) { return Err(SetDynamicStateError::RequirementNotMet { - required_for: "`set_depth_bounds_test_enable`", + required_for: "`AutoCommandBufferBuilder::set_depth_bounds_test_enable`", requires_one_of: RequiresOneOf { api_version: Some(Version::V1_3), features: &["extended_dynamic_state"], @@ -442,7 +463,10 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdSetDepthCompareOp-commandBuffer-cmdpool - if !queue_family_properties.queue_flags.graphics { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS) + { return Err(SetDynamicStateError::NotSupportedByQueueFamily); } @@ -451,7 +475,7 @@ where || self.device().enabled_features().extended_dynamic_state) { return Err(SetDynamicStateError::RequirementNotMet { - required_for: "`set_depth_compare_op`", + required_for: "`AutoCommandBufferBuilder::set_depth_compare_op`", requires_one_of: RequiresOneOf { api_version: Some(Version::V1_3), features: &["extended_dynamic_state"], @@ -488,7 +512,10 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdSetDepthTestEnable-commandBuffer-cmdpool - if !queue_family_properties.queue_flags.graphics { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS) + { return Err(SetDynamicStateError::NotSupportedByQueueFamily); } @@ -497,7 +524,7 @@ where || self.device().enabled_features().extended_dynamic_state) { return Err(SetDynamicStateError::RequirementNotMet { - required_for: "`set_depth_test_enable`", + required_for: "`AutoCommandBufferBuilder::set_depth_test_enable`", requires_one_of: RequiresOneOf { api_version: Some(Version::V1_3), features: &["extended_dynamic_state"], @@ -534,7 +561,10 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdSetDepthWriteEnable-commandBuffer-cmdpool - if !queue_family_properties.queue_flags.graphics { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS) + { return Err(SetDynamicStateError::NotSupportedByQueueFamily); } @@ -543,7 +573,7 @@ where || self.device().enabled_features().extended_dynamic_state) { return Err(SetDynamicStateError::RequirementNotMet { - required_for: "`set_depth_write_enable`", + required_for: "`AutoCommandBufferBuilder::set_depth_write_enable`", requires_one_of: RequiresOneOf { api_version: Some(Version::V1_3), features: &["extended_dynamic_state"], @@ -594,13 +624,16 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdSetDiscardRectangle-commandBuffer-cmdpool - if !queue_family_properties.queue_flags.graphics { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS) + { return Err(SetDynamicStateError::NotSupportedByQueueFamily); } if self.device().enabled_extensions().ext_discard_rectangles { return Err(SetDynamicStateError::RequirementNotMet { - required_for: "`set_discard_rectangle`", + required_for: "`AutoCommandBufferBuilder::set_discard_rectangle`", requires_one_of: RequiresOneOf { device_extensions: &["ext_discard_rectangles"], ..Default::default() @@ -659,7 +692,10 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdSetFrontFace-commandBuffer-cmdpool - if !queue_family_properties.queue_flags.graphics { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS) + { return Err(SetDynamicStateError::NotSupportedByQueueFamily); } @@ -668,7 +704,7 @@ where || self.device().enabled_features().extended_dynamic_state) { return Err(SetDynamicStateError::RequirementNotMet { - required_for: "`set_front_face`", + required_for: "`AutoCommandBufferBuilder::set_front_face`", requires_one_of: RequiresOneOf { api_version: Some(Version::V1_3), features: &["extended_dynamic_state"], @@ -709,13 +745,16 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdSetLineStippleEXT-commandBuffer-cmdpool - if !queue_family_properties.queue_flags.graphics { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS) + { return Err(SetDynamicStateError::NotSupportedByQueueFamily); } if !self.device().enabled_extensions().ext_line_rasterization { return Err(SetDynamicStateError::RequirementNotMet { - required_for: "`set_line_stipple`", + required_for: "`AutoCommandBufferBuilder::set_line_stipple`", requires_one_of: RequiresOneOf { device_extensions: &["ext_line_rasterization"], ..Default::default() @@ -755,7 +794,10 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdSetLineWidth-commandBuffer-cmdpool - if !queue_family_properties.queue_flags.graphics { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS) + { return Err(SetDynamicStateError::NotSupportedByQueueFamily); } @@ -801,7 +843,10 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdSetLogicOpEXT-commandBuffer-cmdpool - if !queue_family_properties.queue_flags.graphics { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS) + { return Err(SetDynamicStateError::NotSupportedByQueueFamily); } @@ -812,7 +857,7 @@ where .extended_dynamic_state2_logic_op { return Err(SetDynamicStateError::RequirementNotMet { - required_for: "`set_logic_op`", + required_for: "`AutoCommandBufferBuilder::set_logic_op`", requires_one_of: RequiresOneOf { features: &["extended_dynamic_state2_logic_op"], ..Default::default() @@ -852,7 +897,10 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdSetPatchControlPointsEXT-commandBuffer-cmdpool - if !queue_family_properties.queue_flags.graphics { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS) + { return Err(SetDynamicStateError::NotSupportedByQueueFamily); } @@ -863,7 +911,7 @@ where .extended_dynamic_state2_patch_control_points { return Err(SetDynamicStateError::RequirementNotMet { - required_for: "`set_patch_control_points`", + required_for: "`AutoCommandBufferBuilder::set_patch_control_points`", requires_one_of: RequiresOneOf { features: &["extended_dynamic_state2_patch_control_points"], ..Default::default() @@ -923,7 +971,10 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdSetPrimitiveRestartEnable-commandBuffer-cmdpool - if !queue_family_properties.queue_flags.graphics { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS) + { return Err(SetDynamicStateError::NotSupportedByQueueFamily); } @@ -932,7 +983,7 @@ where || self.device().enabled_features().extended_dynamic_state2) { return Err(SetDynamicStateError::RequirementNotMet { - required_for: "`set_primitive_restart_enable`", + required_for: "`AutoCommandBufferBuilder::set_primitive_restart_enable`", requires_one_of: RequiresOneOf { api_version: Some(Version::V1_3), features: &["extended_dynamic_state2"], @@ -979,7 +1030,10 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdSetPrimitiveTopology-commandBuffer-cmdpool - if !queue_family_properties.queue_flags.graphics { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS) + { return Err(SetDynamicStateError::NotSupportedByQueueFamily); } @@ -988,7 +1042,7 @@ where || self.device().enabled_features().extended_dynamic_state) { return Err(SetDynamicStateError::RequirementNotMet { - required_for: "`set_primitive_topology`", + required_for: "`AutoCommandBufferBuilder::set_primitive_topology`", requires_one_of: RequiresOneOf { api_version: Some(Version::V1_3), features: &["extended_dynamic_state"], @@ -1006,9 +1060,8 @@ where && !self.device().enabled_features().triangle_fans { return Err(SetDynamicStateError::RequirementNotMet { - required_for: - "this device is a portability subset device, and `topology` is \ - `PrimitiveTopology::TriangleFan`", + required_for: "this device is a portability subset device, and `topology` \ + is `PrimitiveTopology::TriangleFan`", requires_one_of: RequiresOneOf { features: &["triangle_fans"], ..Default::default() @@ -1075,7 +1128,10 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdSetRasterizerDiscardEnable-commandBuffer-cmdpool - if !queue_family_properties.queue_flags.graphics { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS) + { return Err(SetDynamicStateError::NotSupportedByQueueFamily); } @@ -1084,7 +1140,7 @@ where || self.device().enabled_features().extended_dynamic_state2) { return Err(SetDynamicStateError::RequirementNotMet { - required_for: "`set_rasterizer_discard_enable`", + required_for: "`AutoCommandBufferBuilder::set_rasterizer_discard_enable`", requires_one_of: RequiresOneOf { api_version: Some(Version::V1_3), features: &["extended_dynamic_state2"], @@ -1131,7 +1187,10 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdSetScissor-commandBuffer-cmdpool - if !queue_family_properties.queue_flags.graphics { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS) + { return Err(SetDynamicStateError::NotSupportedByQueueFamily); } @@ -1208,7 +1267,10 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdSetScissorWithCount-commandBuffer-cmdpool - if !queue_family_properties.queue_flags.graphics { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS) + { return Err(SetDynamicStateError::NotSupportedByQueueFamily); } @@ -1217,7 +1279,7 @@ where || self.device().enabled_features().extended_dynamic_state) { return Err(SetDynamicStateError::RequirementNotMet { - required_for: "`set_scissor_with_count`", + required_for: "`AutoCommandBufferBuilder::set_scissor_with_count`", requires_one_of: RequiresOneOf { api_version: Some(Version::V1_3), features: &["extended_dynamic_state"], @@ -1282,7 +1344,10 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdSetStencilCompareMask-commandBuffer-cmdpool - if !queue_family_properties.queue_flags.graphics { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS) + { return Err(SetDynamicStateError::NotSupportedByQueueFamily); } @@ -1345,7 +1410,10 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdSetStencilOp-commandBuffer-cmdpool - if !queue_family_properties.queue_flags.graphics { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS) + { return Err(SetDynamicStateError::NotSupportedByQueueFamily); } @@ -1354,7 +1422,7 @@ where || self.device().enabled_features().extended_dynamic_state) { return Err(SetDynamicStateError::RequirementNotMet { - required_for: "`set_stencil_op`", + required_for: "`AutoCommandBufferBuilder::set_stencil_op`", requires_one_of: RequiresOneOf { api_version: Some(Version::V1_3), features: &["extended_dynamic_state"], @@ -1396,7 +1464,10 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdSetStencilReference-commandBuffer-cmdpool - if !queue_family_properties.queue_flags.graphics { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS) + { return Err(SetDynamicStateError::NotSupportedByQueueFamily); } @@ -1428,7 +1499,10 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdSetStencilTestEnable-commandBuffer-cmdpool - if !queue_family_properties.queue_flags.graphics { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS) + { return Err(SetDynamicStateError::NotSupportedByQueueFamily); } @@ -1437,7 +1511,7 @@ where || self.device().enabled_features().extended_dynamic_state) { return Err(SetDynamicStateError::RequirementNotMet { - required_for: "`set_stencil_test_enable`", + required_for: "`AutoCommandBufferBuilder::set_stencil_test_enable`", requires_one_of: RequiresOneOf { api_version: Some(Version::V1_3), features: &["extended_dynamic_state"], @@ -1479,7 +1553,10 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdSetStencilWriteMask-commandBuffer-cmdpool - if !queue_family_properties.queue_flags.graphics { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS) + { return Err(SetDynamicStateError::NotSupportedByQueueFamily); } @@ -1522,7 +1599,10 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdSetViewport-commandBuffer-cmdpool - if !queue_family_properties.queue_flags.graphics { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS) + { return Err(SetDynamicStateError::NotSupportedByQueueFamily); } @@ -1599,7 +1679,10 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdSetViewportWithCount-commandBuffer-cmdpool - if !queue_family_properties.queue_flags.graphics { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS) + { return Err(SetDynamicStateError::NotSupportedByQueueFamily); } @@ -1608,7 +1691,7 @@ where || self.device().enabled_features().extended_dynamic_state) { return Err(SetDynamicStateError::RequirementNotMet { - required_for: "`set_viewport_with_count`", + required_for: "`AutoCommandBufferBuilder::set_viewport_with_count`", requires_one_of: RequiresOneOf { api_version: Some(Version::V1_3), features: &["extended_dynamic_state"], diff --git a/vulkano/src/command_buffer/commands/image.rs b/vulkano/src/command_buffer/commands/image.rs index 67b394ae..fd15e51a 100644 --- a/vulkano/src/command_buffer/commands/image.rs +++ b/vulkano/src/command_buffer/commands/image.rs @@ -14,11 +14,11 @@ use crate::{ sys::UnsafeCommandBufferBuilder, AutoCommandBufferBuilder, CopyError, CopyErrorResource, }, - device::DeviceOwned, - format::{ClearColorValue, ClearDepthStencilValue, NumericType}, + device::{DeviceOwned, QueueFlags}, + format::{ClearColorValue, ClearDepthStencilValue, FormatFeatures, NumericType}, image::{ ImageAccess, ImageAspects, ImageDimensions, ImageLayout, ImageSubresourceLayers, - ImageSubresourceRange, ImageType, SampleCount, SampleCounts, + ImageSubresourceRange, ImageType, ImageUsage, SampleCount, SampleCounts, }, sampler::Filter, sync::{AccessFlags, PipelineMemoryAccess, PipelineStages}, @@ -89,7 +89,10 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdBlitImage2-commandBuffer-cmdpool - if !queue_family_properties.queue_flags.graphics { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS) + { return Err(CopyError::NotSupportedByQueueFamily); } @@ -125,7 +128,7 @@ where let dst_image_type = dst_image.dimensions().image_type(); // VUID-VkBlitImageInfo2-srcImage-00219 - if !src_image.usage().transfer_src { + if !src_image.usage().intersects(ImageUsage::TRANSFER_SRC) { return Err(CopyError::MissingUsage { resource: CopyErrorResource::Source, usage: "transfer_src", @@ -133,7 +136,7 @@ where } // VUID-VkBlitImageInfo2-dstImage-00224 - if !dst_image.usage().transfer_dst { + if !dst_image.usage().intersects(ImageUsage::TRANSFER_DST) { return Err(CopyError::MissingUsage { resource: CopyErrorResource::Destination, usage: "transfer_dst", @@ -141,7 +144,10 @@ where } // VUID-VkBlitImageInfo2-srcImage-01999 - if !src_image.format_features().blit_src { + if !src_image + .format_features() + .intersects(FormatFeatures::BLIT_SRC) + { return Err(CopyError::MissingFormatFeature { resource: CopyErrorResource::Source, format_feature: "blit_src", @@ -149,7 +155,10 @@ where } // VUID-VkBlitImageInfo2-dstImage-02000 - if !dst_image.format_features().blit_dst { + if !dst_image + .format_features() + .intersects(FormatFeatures::BLIT_DST) + { return Err(CopyError::MissingFormatFeature { resource: CopyErrorResource::Destination, 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 if src_image.format() != dst_image.format() { return Err(CopyError::FormatsMismatch { @@ -218,10 +229,7 @@ where return Err(CopyError::SampleCountInvalid { resource: CopyErrorResource::Destination, sample_count: dst_image.samples(), - allowed_sample_counts: SampleCounts { - sample1: true, - ..SampleCounts::empty() - }, + allowed_sample_counts: SampleCounts::SAMPLE_1, }); } @@ -230,10 +238,7 @@ where return Err(CopyError::SampleCountInvalid { resource: CopyErrorResource::Destination, sample_count: dst_image.samples(), - allowed_sample_counts: SampleCounts { - sample1: true, - ..SampleCounts::empty() - }, + allowed_sample_counts: SampleCounts::SAMPLE_1, }); } @@ -260,7 +265,7 @@ where } // 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); } @@ -268,13 +273,19 @@ where Filter::Nearest => (), Filter::Linear => { // 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); } } Filter::Cubic => { // 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); } @@ -300,7 +311,7 @@ where let check_subresource = |resource: CopyErrorResource, image: &dyn ImageAccess, - image_aspects: &ImageAspects, + image_aspects: ImageAspects, subresource: &ImageSubresourceLayers| -> Result<_, CopyError> { // VUID-VkBlitImageInfo2-srcSubresource-01705 @@ -337,12 +348,12 @@ where // VUID-VkBlitImageInfo2-aspectMask-00241 // VUID-VkBlitImageInfo2-aspectMask-00242 - if !image_aspects.contains(&subresource.aspects) { + if !image_aspects.contains(subresource.aspects) { return Err(CopyError::AspectsNotAllowed { resource, region_index, aspects: subresource.aspects, - allowed_aspects: *image_aspects, + allowed_aspects: image_aspects, }); } @@ -356,13 +367,13 @@ where let src_subresource_extent = check_subresource( CopyErrorResource::Source, src_image, - &src_image_aspects, + src_image_aspects, src_subresource, )?; let dst_subresource_extent = check_subresource( CopyErrorResource::Destination, dst_image, - &dst_image_aspects, + dst_image_aspects, dst_subresource, )?; @@ -591,8 +602,9 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdClearColorImage-commandBuffer-cmdpool - if !(queue_family_properties.queue_flags.graphics - || queue_family_properties.queue_flags.compute) + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS | QueueFlags::COMPUTE) { return Err(CopyError::NotSupportedByQueueFamily); } @@ -612,7 +624,7 @@ where assert_eq!(device, image.device()); // VUID-vkCmdClearColorImage-image-00002 - if !image.usage().transfer_dst { + if !image.usage().intersects(ImageUsage::TRANSFER_DST) { return Err(CopyError::MissingUsage { resource: CopyErrorResource::Destination, usage: "transfer_dst", @@ -621,7 +633,10 @@ where if device.api_version() >= Version::V1_1 || device.enabled_extensions().khr_maintenance1 { // VUID-vkCmdClearColorImage-image-01993 - if !image.format_features().transfer_dst { + if !image + .format_features() + .intersects(FormatFeatures::TRANSFER_DST) + { return Err(CopyError::MissingFormatFeature { resource: CopyErrorResource::Destination, format_feature: "transfer_dst", @@ -632,7 +647,7 @@ where let image_aspects = image.format().aspects(); // VUID-vkCmdClearColorImage-image-00007 - if image_aspects.depth || image_aspects.stencil { + if image_aspects.intersects(ImageAspects::DEPTH | ImageAspects::STENCIL) { return Err(CopyError::FormatNotSupported { resource: CopyErrorResource::Destination, format: image.format(), @@ -674,7 +689,7 @@ where assert!(!subresource_range.aspects.is_empty()); // VUID-vkCmdClearColorImage-aspectMask-02498 - if !image_aspects.contains(&subresource_range.aspects) { + if !image_aspects.contains(subresource_range.aspects) { return Err(CopyError::AspectsNotAllowed { resource: CopyErrorResource::Destination, region_index, @@ -743,7 +758,10 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdClearDepthStencilImage-commandBuffer-cmdpool - if !queue_family_properties.queue_flags.graphics { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS) + { return Err(CopyError::NotSupportedByQueueFamily); } @@ -763,7 +781,10 @@ where if device.api_version() >= Version::V1_1 || device.enabled_extensions().khr_maintenance1 { // VUID-vkCmdClearDepthStencilImage-image-01994 - if !image.format_features().transfer_dst { + if !image + .format_features() + .intersects(FormatFeatures::TRANSFER_DST) + { return Err(CopyError::MissingFormatFeature { resource: CopyErrorResource::Destination, format_feature: "transfer_dst", @@ -774,7 +795,7 @@ where let image_aspects = image.format().aspects(); // VUID-vkCmdClearDepthStencilImage-image-00014 - if !(image_aspects.depth || image_aspects.stencil) { + if !image_aspects.intersects(ImageAspects::DEPTH | ImageAspects::STENCIL) { return Err(CopyError::FormatNotSupported { resource: CopyErrorResource::Destination, format: image.format(), @@ -797,8 +818,8 @@ where && !(0.0..=1.0).contains(&clear_value.depth) { return Err(CopyError::RequirementNotMet { - required_for: - "`clear_info.clear_value.depth` is not between `0.0` and `1.0` inclusive", + required_for: "`clear_info.clear_value.depth` is not between `0.0` and `1.0` \ + inclusive", requires_one_of: RequiresOneOf { device_extensions: &["ext_depth_range_unrestricted"], ..Default::default() @@ -818,7 +839,7 @@ where // VUID-vkCmdClearDepthStencilImage-aspectMask-02824 // VUID-vkCmdClearDepthStencilImage-image-02825 // VUID-vkCmdClearDepthStencilImage-image-02826 - if !image_aspects.contains(&subresource_range.aspects) { + if !image_aspects.contains(subresource_range.aspects) { return Err(CopyError::AspectsNotAllowed { resource: CopyErrorResource::Destination, region_index, @@ -860,7 +881,9 @@ where // VUID-vkCmdClearDepthStencilImage-pRanges-02658 // 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 { resource: CopyErrorResource::Destination, usage: "transfer_dst", @@ -868,12 +891,8 @@ where } // VUID-vkCmdClearDepthStencilImage-pRanges-02660 - if !(ImageAspects { - stencil: false, - ..image_aspects_used - }) - .is_empty() - && !image.usage().transfer_dst + if !(image_aspects_used - ImageAspects::STENCIL).is_empty() + && !image.usage().intersects(ImageUsage::TRANSFER_DST) { return Err(CopyError::MissingUsage { resource: CopyErrorResource::Destination, @@ -917,7 +936,10 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdResolveImage2-commandBuffer-cmdpool - if !queue_family_properties.queue_flags.graphics { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS) + { return Err(CopyError::NotSupportedByQueueFamily); } @@ -948,15 +970,12 @@ where return Err(CopyError::SampleCountInvalid { resource: CopyErrorResource::Source, sample_count: dst_image.samples(), - allowed_sample_counts: SampleCounts { - sample2: true, - sample4: true, - sample8: true, - sample16: true, - sample32: true, - sample64: true, - ..SampleCounts::empty() - }, + allowed_sample_counts: SampleCounts::SAMPLE_2 + | SampleCounts::SAMPLE_4 + | SampleCounts::SAMPLE_8 + | SampleCounts::SAMPLE_16 + | SampleCounts::SAMPLE_32 + | SampleCounts::SAMPLE_64, }); } @@ -965,15 +984,15 @@ where return Err(CopyError::SampleCountInvalid { resource: CopyErrorResource::Destination, sample_count: dst_image.samples(), - allowed_sample_counts: SampleCounts { - sample1: true, - ..SampleCounts::empty() - }, + allowed_sample_counts: SampleCounts::SAMPLE_1, }); } // VUID-VkResolveImageInfo2-dstImage-02003 - if !dst_image.format_features().color_attachment { + if !dst_image + .format_features() + .intersects(FormatFeatures::COLOR_ATTACHMENT) + { return Err(CopyError::MissingFormatFeature { resource: CopyErrorResource::Destination, format_feature: "color_attachment", @@ -1012,7 +1031,10 @@ where // Should be guaranteed by the requirement that formats match, and that the destination // 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() { let &ImageResolve { @@ -1062,20 +1084,12 @@ where // VUID-VkImageSubresourceLayers-aspectMask-requiredbitmask // VUID-VkImageResolve2-aspectMask-00266 - if subresource.aspects - != (ImageAspects { - color: true, - ..ImageAspects::empty() - }) - { + if subresource.aspects != (ImageAspects::COLOR) { return Err(CopyError::AspectsNotAllowed { resource, region_index, aspects: subresource.aspects, - allowed_aspects: ImageAspects { - color: true, - ..ImageAspects::empty() - }, + allowed_aspects: ImageAspects::COLOR, }); } @@ -1216,14 +1230,8 @@ impl SyncCommandBufferBuilder { image: src_image.clone(), subresource_range: src_subresource.clone().into(), memory: PipelineMemoryAccess { - stages: PipelineStages { - all_transfer: true, - ..PipelineStages::empty() - }, - access: AccessFlags { - transfer_read: true, - ..AccessFlags::empty() - }, + stages: PipelineStages::ALL_TRANSFER, + access: AccessFlags::TRANSFER_READ, exclusive: false, }, start_layout: src_image_layout, @@ -1236,14 +1244,8 @@ impl SyncCommandBufferBuilder { image: dst_image.clone(), subresource_range: dst_subresource.clone().into(), memory: PipelineMemoryAccess { - stages: PipelineStages { - all_transfer: true, - ..PipelineStages::empty() - }, - access: AccessFlags { - transfer_write: true, - ..AccessFlags::empty() - }, + stages: PipelineStages::ALL_TRANSFER, + access: AccessFlags::TRANSFER_WRITE, exclusive: true, }, start_layout: dst_image_layout, @@ -1308,14 +1310,8 @@ impl SyncCommandBufferBuilder { image: image.clone(), subresource_range, memory: PipelineMemoryAccess { - stages: PipelineStages { - all_transfer: true, - ..PipelineStages::empty() - }, - access: AccessFlags { - transfer_write: true, - ..AccessFlags::empty() - }, + stages: PipelineStages::ALL_TRANSFER, + access: AccessFlags::TRANSFER_WRITE, exclusive: true, }, start_layout: image_layout, @@ -1379,14 +1375,8 @@ impl SyncCommandBufferBuilder { image: image.clone(), subresource_range, memory: PipelineMemoryAccess { - stages: PipelineStages { - all_transfer: true, - ..PipelineStages::empty() - }, - access: AccessFlags { - transfer_write: true, - ..AccessFlags::empty() - }, + stages: PipelineStages::ALL_TRANSFER, + access: AccessFlags::TRANSFER_WRITE, exclusive: true, }, start_layout: image_layout, @@ -1460,14 +1450,8 @@ impl SyncCommandBufferBuilder { image: src_image.clone(), subresource_range: src_subresource.clone().into(), memory: PipelineMemoryAccess { - stages: PipelineStages { - all_transfer: true, - ..PipelineStages::empty() - }, - access: AccessFlags { - transfer_read: true, - ..AccessFlags::empty() - }, + stages: PipelineStages::ALL_TRANSFER, + access: AccessFlags::TRANSFER_READ, exclusive: false, }, start_layout: src_image_layout, @@ -1480,14 +1464,8 @@ impl SyncCommandBufferBuilder { image: dst_image.clone(), subresource_range: dst_subresource.clone().into(), memory: PipelineMemoryAccess { - stages: PipelineStages { - all_transfer: true, - ..PipelineStages::empty() - }, - access: AccessFlags { - transfer_write: true, - ..AccessFlags::empty() - }, + stages: PipelineStages::ALL_TRANSFER, + access: AccessFlags::TRANSFER_WRITE, exclusive: true, }, start_layout: dst_image_layout, diff --git a/vulkano/src/command_buffer/commands/pipeline.rs b/vulkano/src/command_buffer/commands/pipeline.rs index feee2d19..e9bffb4d 100644 --- a/vulkano/src/command_buffer/commands/pipeline.rs +++ b/vulkano/src/command_buffer/commands/pipeline.rs @@ -8,7 +8,7 @@ // according to those terms. use crate::{ - buffer::{view::BufferViewAbstract, BufferAccess, TypedBufferAccess}, + buffer::{view::BufferViewAbstract, BufferAccess, BufferUsage, TypedBufferAccess}, command_buffer::{ allocator::CommandBufferAllocator, auto::{RenderPassState, RenderPassStateType}, @@ -18,10 +18,11 @@ use crate::{ DrawIndirectCommand, SubpassContents, }, descriptor_set::{layout::DescriptorType, DescriptorBindingResources}, - device::DeviceOwned, - format::Format, + device::{DeviceOwned, QueueFlags}, + format::{Format, FormatFeatures}, image::{ - view::ImageViewType, ImageAccess, ImageSubresourceRange, ImageViewAbstract, SampleCount, + view::ImageViewType, ImageAccess, ImageAspects, ImageSubresourceRange, ImageViewAbstract, + SampleCount, }, pipeline::{ graphics::{ @@ -76,7 +77,10 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdDispatch-commandBuffer-cmdpool - if !queue_family_properties.queue_flags.compute { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::COMPUTE) + { return Err(PipelineExecutionError::NotSupportedByQueueFamily); } @@ -142,7 +146,10 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdDispatchIndirect-commandBuffer-cmdpool - if !queue_family_properties.queue_flags.compute { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::COMPUTE) + { return Err(PipelineExecutionError::NotSupportedByQueueFamily); } @@ -549,7 +556,7 @@ where assert_eq!(self.device(), buffer.device()); // VUID-vkCmdDispatchIndirect-buffer-02709 - if !buffer.inner().buffer.usage().indirect_buffer { + if !buffer.usage().intersects(BufferUsage::INDIRECT_BUFFER) { return Err(PipelineExecutionError::IndirectBufferMissingUsage); } @@ -650,7 +657,9 @@ where // VUID-vkCmdDispatch-OpTypeImage-06423 if reqs.image_format.is_none() && 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( DescriptorResourceInvalidError::StorageWriteWithoutFormatNotSupported, @@ -660,7 +669,9 @@ where // VUID-vkCmdDispatch-OpTypeImage-06424 if reqs.image_format.is_none() && 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( DescriptorResourceInvalidError::StorageReadWithoutFormatNotSupported, @@ -674,7 +685,9 @@ where let check_image_view_common = |index: u32, image_view: &Arc| { // VUID-vkCmdDispatch-None-02691 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); } @@ -683,7 +696,9 @@ where // VUID-vkCmdDispatch-OpTypeImage-06423 if reqs.image_format.is_none() && 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( DescriptorResourceInvalidError::StorageWriteWithoutFormatNotSupported, @@ -693,7 +708,9 @@ where // VUID-vkCmdDispatch-OpTypeImage-06424 if reqs.image_format.is_none() && 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( DescriptorResourceInvalidError::StorageReadWithoutFormatNotSupported, @@ -748,11 +765,16 @@ where if let Some(scalar_type) = reqs.image_scalar_type { let aspects = image_view.subresource_range().aspects; 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() - } else if aspects.depth { + } else if aspects.intersects(ImageAspects::DEPTH) { image_view.format().unwrap().type_depth().unwrap() - } else if aspects.stencil { + } else if aspects.intersects(ImageAspects::STENCIL) { image_view.format().unwrap().type_stencil().unwrap() } else { // Per `ImageViewBuilder::aspects` and @@ -1125,7 +1147,10 @@ where // VUID? if !device.enabled_features().primitive_topology_list_restart { 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 { features: &["primitive_topology_list_restart"], ..Default::default() @@ -1140,7 +1165,10 @@ where .primitive_topology_patch_list_restart { 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 { features: &["primitive_topology_patch_list_restart"], ..Default::default() @@ -1934,20 +1962,10 @@ impl SyncCommandBufferBuilder { | DescriptorType::UniformTexelBuffer | DescriptorType::StorageTexelBuffer | DescriptorType::StorageBuffer - | DescriptorType::StorageBufferDynamic => AccessFlags { - shader_read: true, - shader_write: false, - ..AccessFlags::empty() - }, - DescriptorType::InputAttachment => AccessFlags { - input_attachment_read: true, - ..AccessFlags::empty() - }, + | DescriptorType::StorageBufferDynamic => AccessFlags::SHADER_READ, + DescriptorType::InputAttachment => AccessFlags::INPUT_ATTACHMENT_READ, DescriptorType::UniformBuffer | DescriptorType::UniformBufferDynamic => { - AccessFlags { - uniform_read: true, - ..AccessFlags::empty() - } + AccessFlags::UNIFORM_READ } }, exclusive: false, @@ -1956,8 +1974,12 @@ impl SyncCommandBufferBuilder { let access = (0..).map(|index| { let mut access = access; let mutable = reqs.storage_write.contains(&index); - access.access.shader_write = mutable; access.exclusive = mutable; + + if mutable { + access.access |= AccessFlags::SHADER_WRITE; + } + access }); @@ -2080,14 +2102,8 @@ impl SyncCommandBufferBuilder { buffer: vertex_buffer.clone(), range: 0..vertex_buffer.size(), // TODO: memory: PipelineMemoryAccess { - stages: PipelineStages { - vertex_input: true, - ..PipelineStages::empty() - }, - access: AccessFlags { - vertex_attribute_read: true, - ..AccessFlags::empty() - }, + stages: PipelineStages::VERTEX_INPUT, + access: AccessFlags::VERTEX_ATTRIBUTE_READ, exclusive: false, }, }, @@ -2103,14 +2119,8 @@ impl SyncCommandBufferBuilder { buffer: index_buffer.clone(), range: 0..index_buffer.size(), // TODO: memory: PipelineMemoryAccess { - stages: PipelineStages { - vertex_input: true, - ..PipelineStages::empty() - }, - access: AccessFlags { - index_read: true, - ..AccessFlags::empty() - }, + stages: PipelineStages::VERTEX_INPUT, + access: AccessFlags::INDEX_READ, exclusive: false, }, }, @@ -2128,14 +2138,8 @@ impl SyncCommandBufferBuilder { buffer: indirect_buffer.clone(), range: 0..indirect_buffer.size(), // TODO: memory: PipelineMemoryAccess { - stages: PipelineStages { - draw_indirect: true, - ..PipelineStages::empty() - }, // TODO: is draw_indirect correct for dispatch too? - access: AccessFlags { - indirect_command_read: true, - ..AccessFlags::empty() - }, + stages: PipelineStages::DRAW_INDIRECT, // TODO: is draw_indirect correct for dispatch too? + access: AccessFlags::INDIRECT_COMMAND_READ, exclusive: false, }, }, @@ -2174,7 +2178,10 @@ impl UnsafeCommandBufferBuilder { let inner = buffer.inner(); 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); (fns.v1_0.cmd_dispatch_indirect)(self.handle, inner.buffer.handle(), inner.offset); @@ -2238,7 +2245,10 @@ impl UnsafeCommandBufferBuilder { let inner = buffer.inner(); 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)( self.handle, @@ -2261,7 +2271,10 @@ impl UnsafeCommandBufferBuilder { let inner = buffer.inner(); 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)( self.handle, diff --git a/vulkano/src/command_buffer/commands/query.rs b/vulkano/src/command_buffer/commands/query.rs index ea6aba90..10bdc17c 100644 --- a/vulkano/src/command_buffer/commands/query.rs +++ b/vulkano/src/command_buffer/commands/query.rs @@ -8,7 +8,7 @@ // according to those terms. use crate::{ - buffer::TypedBufferAccess, + buffer::{BufferUsage, TypedBufferAccess}, command_buffer::{ allocator::CommandBufferAllocator, auto::QueryState, @@ -16,7 +16,7 @@ use crate::{ sys::UnsafeCommandBufferBuilder, AutoCommandBufferBuilder, }, - device::DeviceOwned, + device::{DeviceOwned, QueueFlags}, query::{ QueriesRange, Query, QueryControlFlags, QueryPool, QueryResultElement, QueryResultFlags, QueryType, @@ -80,8 +80,9 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdBeginQuery-commandBuffer-cmdpool - if !(queue_family_properties.queue_flags.graphics - || queue_family_properties.queue_flags.compute) + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS | QueueFlags::COMPUTE) { return Err(QueryError::NotSupportedByQueueFamily); } @@ -101,14 +102,19 @@ where QueryType::Occlusion => { // VUID-vkCmdBeginQuery-commandBuffer-cmdpool // // VUID-vkCmdBeginQuery-queryType-00803 - if !queue_family_properties.queue_flags.graphics { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS) + { return Err(QueryError::NotSupportedByQueueFamily); } // 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 { - required_for: "`flags.precise` is set", + required_for: "`flags` contains `QueryControlFlags::PRECISE`", requires_one_of: RequiresOneOf { features: &["occlusion_query_precise"], ..Default::default() @@ -120,15 +126,20 @@ where // VUID-vkCmdBeginQuery-commandBuffer-cmdpool // VUID-vkCmdBeginQuery-queryType-00804 // 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() - && !queue_family_properties.queue_flags.graphics + && !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS) { return Err(QueryError::NotSupportedByQueueFamily); } // VUID-vkCmdBeginQuery-queryType-00800 - if flags.precise { + if flags.intersects(QueryControlFlags::PRECISE) { return Err(QueryError::InvalidFlags); } } @@ -179,8 +190,9 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdEndQuery-commandBuffer-cmdpool - if !(queue_family_properties.queue_flags.graphics - || queue_family_properties.queue_flags.compute) + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS | QueueFlags::COMPUTE) { return Err(QueryError::NotSupportedByQueueFamily); } @@ -243,7 +255,7 @@ where if !device.enabled_features().synchronization2 && PipelineStages::from(stage).is_2() { return Err(QueryError::RequirementNotMet { - required_for: "`stage` has bits set from `VkPipelineStageFlagBits2`", + required_for: "`stage` has flags set from `VkPipelineStageFlagBits2`", requires_one_of: RequiresOneOf { features: &["synchronization2"], ..Default::default() @@ -257,12 +269,13 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdWriteTimestamp2-commandBuffer-cmdpool - if !(queue_family_properties.queue_flags.transfer - || queue_family_properties.queue_flags.graphics - || queue_family_properties.queue_flags.compute - || queue_family_properties.queue_flags.video_decode - || queue_family_properties.queue_flags.video_encode) - { + if !queue_family_properties.queue_flags.intersects( + QueueFlags::TRANSFER + | QueueFlags::GRAPHICS + | QueueFlags::COMPUTE + | QueueFlags::VIDEO_DECODE + | QueueFlags::VIDEO_ENCODE, + ) { return Err(QueryError::NotSupportedByQueueFamily); } @@ -294,7 +307,8 @@ where // VUID-vkCmdWriteTimestamp2-stage-03930 if !device.enabled_features().tessellation_shader { 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 { features: &["tessellation_shader"], ..Default::default() @@ -433,12 +447,15 @@ where /// 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 - /// will be written for each query in the range, plus 1 extra element per query if - /// [`QueryResultFlags::with_availability`] is enabled. + /// [`query_pool.ty().result_len()`] elements will be written for each query in the range, plus + /// 1 extra element per query if [`QueryResultFlags::WITH_AVAILABILITY`] is enabled. /// 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( &mut self, query_pool: Arc, @@ -458,8 +475,8 @@ where )?; unsafe { - let per_query_len = - query_pool.query_type().result_len() + flags.with_availability as DeviceSize; + let per_query_len = query_pool.query_type().result_len() + + flags.intersects(QueryResultFlags::WITH_AVAILABILITY) as DeviceSize; let stride = per_query_len * std::mem::size_of::() as DeviceSize; self.inner .copy_query_pool_results(query_pool, queries, destination, stride, flags)?; @@ -482,8 +499,9 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdCopyQueryPoolResults-commandBuffer-cmdpool - if !(queue_family_properties.queue_flags.graphics - || queue_family_properties.queue_flags.compute) + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS | QueueFlags::COMPUTE) { return Err(QueryError::NotSupportedByQueueFamily); } @@ -513,8 +531,8 @@ where .ok_or(QueryError::OutOfRange)?; let count = queries.end - queries.start; - let per_query_len = - query_pool.query_type().result_len() + flags.with_availability as DeviceSize; + let per_query_len = query_pool.query_type().result_len() + + flags.intersects(QueryResultFlags::WITH_AVAILABILITY) as DeviceSize; let required_len = per_query_len * count as DeviceSize; // VUID-vkCmdCopyQueryPoolResults-dstBuffer-00824 @@ -526,12 +544,18 @@ where } // VUID-vkCmdCopyQueryPoolResults-dstBuffer-00825 - if !buffer_inner.buffer.usage().transfer_dst { + if !buffer_inner + .buffer + .usage() + .intersects(BufferUsage::TRANSFER_DST) + { return Err(QueryError::DestinationMissingUsage); } // 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); } @@ -571,8 +595,9 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdResetQueryPool-commandBuffer-cmdpool - if !(queue_family_properties.queue_flags.graphics - || queue_family_properties.queue_flags.compute) + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS | QueueFlags::COMPUTE) { return Err(QueryError::NotSupportedByQueueFamily); } @@ -734,14 +759,8 @@ impl SyncCommandBufferBuilder { buffer: destination.clone(), range: 0..destination.size(), // TODO: memory: PipelineMemoryAccess { - stages: PipelineStages { - all_transfer: true, - ..PipelineStages::empty() - }, - access: AccessFlags { - transfer_write: true, - ..AccessFlags::empty() - }, + stages: PipelineStages::ALL_TRANSFER, + access: AccessFlags::TRANSFER_WRITE, exclusive: true, }, }, @@ -796,12 +815,12 @@ impl UnsafeCommandBufferBuilder { #[inline] pub unsafe fn begin_query(&mut self, query: Query<'_>, flags: QueryControlFlags) { let fns = self.device.fns(); - let flags = if flags.precise { - ash::vk::QueryControlFlags::PRECISE - } else { - ash::vk::QueryControlFlags::empty() - }; - (fns.v1_0.cmd_begin_query)(self.handle, query.pool().handle(), query.index(), flags); + (fns.v1_0.cmd_begin_query)( + self.handle, + query.pool().handle(), + query.index(), + flags.into(), + ); } /// Calls `vkCmdEndQuery` on the builder. @@ -857,7 +876,10 @@ impl UnsafeCommandBufferBuilder { let destination = destination.inner(); let range = queries.range(); 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::() as DeviceSize == 0); debug_assert!(stride % size_of::() as DeviceSize == 0); diff --git a/vulkano/src/command_buffer/commands/render_pass.rs b/vulkano/src/command_buffer/commands/render_pass.rs index 0f7ccac1..46bcb7bf 100644 --- a/vulkano/src/command_buffer/commands/render_pass.rs +++ b/vulkano/src/command_buffer/commands/render_pass.rs @@ -18,9 +18,9 @@ use crate::{ sys::UnsafeCommandBufferBuilder, AutoCommandBufferBuilder, SubpassContents, }, - device::DeviceOwned, + device::{DeviceOwned, QueueFlags}, format::{ClearColorValue, ClearValue, Format, NumericType}, - image::{ImageLayout, ImageViewAbstract, SampleCount}, + image::{ImageAspects, ImageLayout, ImageUsage, ImageViewAbstract, SampleCount}, render_pass::{ AttachmentDescription, Framebuffer, LoadOp, RenderPass, ResolveMode, StoreOp, SubpassDescription, @@ -103,7 +103,10 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdBeginRenderPass2-commandBuffer-cmdpool - if !queue_family_properties.queue_flags.graphics { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS) + { return Err(RenderPassError::NotSupportedByQueueFamily); } @@ -155,7 +158,7 @@ where match layout { ImageLayout::ColorAttachmentOptimal => { // VUID-vkCmdBeginRenderPass2-initialLayout-03094 - if !image_view.usage().color_attachment { + if !image_view.usage().intersects(ImageUsage::COLOR_ATTACHMENT) { return Err(RenderPassError::AttachmentImageMissingUsage { attachment_index, usage: "color_attachment", @@ -167,7 +170,10 @@ where | ImageLayout::DepthStencilAttachmentOptimal | ImageLayout::DepthStencilReadOnlyOptimal => { // VUID-vkCmdBeginRenderPass2-initialLayout-03096 - if !image_view.usage().depth_stencil_attachment { + if !image_view + .usage() + .intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT) + { return Err(RenderPassError::AttachmentImageMissingUsage { attachment_index, usage: "depth_stencil_attachment", @@ -176,7 +182,10 @@ where } ImageLayout::ShaderReadOnlyOptimal => { // 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 { attachment_index, usage: "sampled or input_attachment", @@ -185,7 +194,7 @@ where } ImageLayout::TransferSrcOptimal => { // VUID-vkCmdBeginRenderPass2-initialLayout-03098 - if !image_view.usage().transfer_src { + if !image_view.usage().intersects(ImageUsage::TRANSFER_SRC) { return Err(RenderPassError::AttachmentImageMissingUsage { attachment_index, usage: "transfer_src", @@ -194,7 +203,7 @@ where } ImageLayout::TransferDstOptimal => { // VUID-vkCmdBeginRenderPass2-initialLayout-03099 - if !image_view.usage().transfer_dst { + if !image_view.usage().intersects(ImageUsage::TRANSFER_DST) { return Err(RenderPassError::AttachmentImageMissingUsage { attachment_index, usage: "transfer_dst", @@ -228,7 +237,7 @@ where match atch_ref.layout { ImageLayout::ColorAttachmentOptimal => { // VUID-vkCmdBeginRenderPass2-initialLayout-03094 - if !image_view.usage().color_attachment { + if !image_view.usage().intersects(ImageUsage::COLOR_ATTACHMENT) { return Err(RenderPassError::AttachmentImageMissingUsage { attachment_index: atch_ref.attachment, usage: "color_attachment", @@ -240,7 +249,10 @@ where | ImageLayout::DepthStencilAttachmentOptimal | ImageLayout::DepthStencilReadOnlyOptimal => { // VUID-vkCmdBeginRenderPass2-initialLayout-03096 - if !image_view.usage().depth_stencil_attachment { + if !image_view + .usage() + .intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT) + { return Err(RenderPassError::AttachmentImageMissingUsage { attachment_index: atch_ref.attachment, usage: "depth_stencil_attachment", @@ -249,7 +261,10 @@ where } ImageLayout::ShaderReadOnlyOptimal => { // 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 { attachment_index: atch_ref.attachment, usage: "sampled or input_attachment", @@ -258,7 +273,7 @@ where } ImageLayout::TransferSrcOptimal => { // VUID-vkCmdBeginRenderPass2-initialLayout-03098 - if !image_view.usage().transfer_src { + if !image_view.usage().intersects(ImageUsage::TRANSFER_SRC) { return Err(RenderPassError::AttachmentImageMissingUsage { attachment_index: atch_ref.attachment, usage: "transfer_src", @@ -267,7 +282,7 @@ where } ImageLayout::TransferDstOptimal => { // VUID-vkCmdBeginRenderPass2-initialLayout-03099 - if !image_view.usage().transfer_dst { + if !image_view.usage().intersects(ImageUsage::TRANSFER_DST) { return Err(RenderPassError::AttachmentImageMissingUsage { attachment_index: atch_ref.attachment, usage: "transfer_dst", @@ -344,9 +359,9 @@ where } } else { let attachment_aspects = attachment_format.aspects(); - let need_depth = - attachment_aspects.depth && attachment_desc.load_op == LoadOp::Clear; - let need_stencil = attachment_aspects.stencil + let need_depth = attachment_aspects.intersects(ImageAspects::DEPTH) + && attachment_desc.load_op == LoadOp::Clear; + let need_stencil = attachment_aspects.intersects(ImageAspects::STENCIL) && attachment_desc.stencil_load_op == LoadOp::Clear; if need_depth && need_stencil { @@ -456,10 +471,10 @@ where } // VUID-vkCmdNextSubpass2-commandBuffer-cmdpool - debug_assert!({ - let queue_family_properties = self.queue_family_properties(); - queue_family_properties.queue_flags.graphics - }); + debug_assert!(self + .queue_family_properties() + .queue_flags + .intersects(QueueFlags::GRAPHICS)); // VUID-vkCmdNextSubpass2-bufferlevel // Ensured by the type of the impl block @@ -514,10 +529,10 @@ where } // VUID-vkCmdEndRenderPass2-commandBuffer-cmdpool - debug_assert!({ - let queue_family_properties = self.queue_family_properties(); - queue_family_properties.queue_flags.graphics - }); + debug_assert!(self + .queue_family_properties() + .queue_flags + .intersects(QueueFlags::GRAPHICS)); // VUID-vkCmdEndRenderPass2-bufferlevel // Ensured by the type of the impl block @@ -678,7 +693,7 @@ where // VUID-vkCmdBeginRendering-dynamicRendering-06446 if !device.enabled_features().dynamic_rendering { return Err(RenderPassError::RequirementNotMet { - required_for: "`begin_rendering`", + required_for: "`AutoCommandBufferBuilder::begin_rendering`", requires_one_of: RequiresOneOf { features: &["dynamic_rendering"], ..Default::default() @@ -689,7 +704,10 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdBeginRendering-commandBuffer-cmdpool - if !queue_family_properties.queue_flags.graphics { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS) + { return Err(RenderPassError::NotSupportedByQueueFamily); } @@ -785,7 +803,7 @@ where store_op.validate_device(device)?; // VUID-VkRenderingInfo-colorAttachmentCount-06087 - if !image_view.usage().color_attachment { + if !image_view.usage().intersects(ImageUsage::COLOR_ATTACHMENT) { return Err(RenderPassError::ColorAttachmentMissingUsage { attachment_index }); } @@ -942,12 +960,15 @@ where let image_aspects = image_view.format().unwrap().aspects(); // VUID-VkRenderingInfo-pDepthAttachment-06547 - if !image_aspects.depth { + if !image_aspects.intersects(ImageAspects::DEPTH) { return Err(RenderPassError::DepthAttachmentFormatUsageNotSupported); } // VUID-VkRenderingInfo-pDepthAttachment-06088 - if !image_view.usage().depth_stencil_attachment { + if !image_view + .usage() + .intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT) + { return Err(RenderPassError::DepthAttachmentMissingUsage); } @@ -1003,7 +1024,7 @@ where // VUID-VkRenderingInfo-pDepthAttachment-06102 if !properties .supported_depth_resolve_modes - .map_or(false, |modes| modes.contains_mode(mode)) + .map_or(false, |modes| modes.contains_enum(mode)) { return Err(RenderPassError::DepthAttachmentResolveModeNotSupported); } @@ -1069,12 +1090,15 @@ where let image_aspects = image_view.format().unwrap().aspects(); // VUID-VkRenderingInfo-pStencilAttachment-06548 - if !image_aspects.stencil { + if !image_aspects.intersects(ImageAspects::STENCIL) { return Err(RenderPassError::StencilAttachmentFormatUsageNotSupported); } // VUID-VkRenderingInfo-pStencilAttachment-06089 - if !image_view.usage().depth_stencil_attachment { + if !image_view + .usage() + .intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT) + { return Err(RenderPassError::StencilAttachmentMissingUsage); } @@ -1130,7 +1154,7 @@ where // VUID-VkRenderingInfo-pStencilAttachment-06103 if !properties .supported_stencil_resolve_modes - .map_or(false, |modes| modes.contains_mode(mode)) + .map_or(false, |modes| modes.contains_enum(mode)) { return Err(RenderPassError::StencilAttachmentResolveModeNotSupported); } @@ -1251,10 +1275,10 @@ where } // VUID-vkCmdEndRendering-commandBuffer-cmdpool - debug_assert!({ - let queue_family_properties = self.queue_family_properties(); - queue_family_properties.queue_flags.graphics - }); + debug_assert!(self + .queue_family_properties() + .queue_flags + .intersects(QueueFlags::GRAPHICS)); Ok(()) } @@ -1416,8 +1440,9 @@ where if matches!( clear_attachment, 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 { clear_attachment, attachment_format: None, @@ -1428,8 +1453,9 @@ where if matches!( clear_attachment, 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 { clear_attachment, attachment_format: None, @@ -1502,10 +1528,10 @@ where } // VUID-vkCmdClearAttachments-commandBuffer-cmdpool - debug_assert!({ - let queue_family_properties = self.queue_family_properties(); - queue_family_properties.queue_flags.graphics - }); + debug_assert!(self + .queue_family_properties() + .queue_flags + .intersects(QueueFlags::GRAPHICS)); Ok(()) } @@ -1559,18 +1585,12 @@ impl SyncCommandBufferBuilder { image: image_view.image(), subresource_range: image_view.subresource_range().clone(), memory: PipelineMemoryAccess { - stages: PipelineStages { - all_commands: true, - ..PipelineStages::empty() - }, // TODO: wrong! - access: AccessFlags { - input_attachment_read: true, - color_attachment_read: true, - color_attachment_write: true, - depth_stencil_attachment_read: true, - depth_stencil_attachment_write: true, - ..AccessFlags::empty() - }, // TODO: suboptimal + stages: PipelineStages::ALL_COMMANDS, // TODO: wrong! + access: AccessFlags::INPUT_ATTACHMENT_READ + | AccessFlags::COLOR_ATTACHMENT_READ + | AccessFlags::COLOR_ATTACHMENT_WRITE + | AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ + | AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE, // TODO: suboptimal exclusive: true, // TODO: suboptimal ; note: remember to always pass true if desc.initial_layout != desc.final_layout }, start_layout: desc.initial_layout, @@ -1696,16 +1716,10 @@ impl SyncCommandBufferBuilder { image: image_view.image(), subresource_range: image_view.subresource_range().clone(), memory: PipelineMemoryAccess { - stages: PipelineStages { - all_commands: true, - ..PipelineStages::empty() - }, // TODO: wrong! - access: AccessFlags { - color_attachment_read: true, - color_attachment_write: true, - ..AccessFlags::empty() - }, // TODO: suboptimal - exclusive: true, // TODO: suboptimal + stages: PipelineStages::ALL_COMMANDS, // TODO: wrong! + access: AccessFlags::COLOR_ATTACHMENT_READ + | AccessFlags::COLOR_ATTACHMENT_WRITE, // TODO: suboptimal + exclusive: true, // TODO: suboptimal }, start_layout: image_layout, end_layout: image_layout, @@ -1724,16 +1738,10 @@ impl SyncCommandBufferBuilder { image: image_view.image(), subresource_range: image_view.subresource_range().clone(), memory: PipelineMemoryAccess { - stages: PipelineStages { - all_commands: true, - ..PipelineStages::empty() - }, // TODO: wrong! - access: AccessFlags { - color_attachment_read: true, - color_attachment_write: true, - ..AccessFlags::empty() - }, // TODO: suboptimal - exclusive: true, // TODO: suboptimal + stages: PipelineStages::ALL_COMMANDS, // TODO: wrong! + access: AccessFlags::COLOR_ATTACHMENT_READ + | AccessFlags::COLOR_ATTACHMENT_WRITE, // TODO: suboptimal + exclusive: true, // TODO: suboptimal }, start_layout: image_layout, end_layout: image_layout, @@ -1762,16 +1770,10 @@ impl SyncCommandBufferBuilder { image: image_view.image(), subresource_range: image_view.subresource_range().clone(), memory: PipelineMemoryAccess { - stages: PipelineStages { - all_commands: true, - ..PipelineStages::empty() - }, // TODO: wrong! - access: AccessFlags { - depth_stencil_attachment_read: true, - depth_stencil_attachment_write: true, - ..AccessFlags::empty() - }, // TODO: suboptimal - exclusive: true, // TODO: suboptimal + stages: PipelineStages::ALL_COMMANDS, // TODO: wrong! + access: AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ + | AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE, // TODO: suboptimal + exclusive: true, // TODO: suboptimal }, start_layout: image_layout, end_layout: image_layout, @@ -1790,15 +1792,9 @@ impl SyncCommandBufferBuilder { image: image_view.image(), subresource_range: image_view.subresource_range().clone(), memory: PipelineMemoryAccess { - stages: PipelineStages { - all_commands: true, - ..PipelineStages::empty() - }, // TODO: wrong! - access: AccessFlags { - depth_stencil_attachment_read: true, - depth_stencil_attachment_write: true, - ..AccessFlags::empty() - }, // TODO: suboptimal + stages: PipelineStages::ALL_COMMANDS, // TODO: wrong! + access: AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ + | AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE, // TODO: suboptimal exclusive: true, // TODO: suboptimal }, start_layout: image_layout, @@ -1828,16 +1824,10 @@ impl SyncCommandBufferBuilder { image: image_view.image(), subresource_range: image_view.subresource_range().clone(), memory: PipelineMemoryAccess { - stages: PipelineStages { - all_commands: true, - ..PipelineStages::empty() - }, // TODO: wrong! - access: AccessFlags { - depth_stencil_attachment_read: true, - depth_stencil_attachment_write: true, - ..AccessFlags::empty() - }, // TODO: suboptimal - exclusive: true, // TODO: suboptimal + stages: PipelineStages::ALL_COMMANDS, // TODO: wrong! + access: AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ + | AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE, // TODO: suboptimal + exclusive: true, // TODO: suboptimal }, start_layout: image_layout, end_layout: image_layout, @@ -1856,15 +1846,9 @@ impl SyncCommandBufferBuilder { image: image_view.image(), subresource_range: image_view.subresource_range().clone(), memory: PipelineMemoryAccess { - stages: PipelineStages { - all_commands: true, - ..PipelineStages::empty() - }, // TODO: wrong! - access: AccessFlags { - depth_stencil_attachment_read: true, - depth_stencil_attachment_write: true, - ..AccessFlags::empty() - }, // TODO: suboptimal + stages: PipelineStages::ALL_COMMANDS, // TODO: wrong! + access: AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ + | AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE, // TODO: suboptimal exclusive: true, // TODO: suboptimal }, start_layout: image_layout, @@ -2429,7 +2413,7 @@ impl RenderingAttachmentInfo { #[inline] pub fn image_view(image_view: Arc) -> Self { 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 } else { ImageLayout::ColorAttachmentOptimal @@ -2473,7 +2457,7 @@ impl RenderingAttachmentResolveInfo { #[inline] pub fn image_view(image_view: Arc) -> Self { 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 } else { ImageLayout::ColorAttachmentOptimal diff --git a/vulkano/src/command_buffer/commands/secondary.rs b/vulkano/src/command_buffer/commands/secondary.rs index 53759759..d711ddbc 100644 --- a/vulkano/src/command_buffer/commands/secondary.rs +++ b/vulkano/src/command_buffer/commands/secondary.rs @@ -16,7 +16,7 @@ use crate::{ AutoCommandBufferBuilder, CommandBufferExecError, CommandBufferInheritanceRenderPassType, CommandBufferUsage, SecondaryCommandBufferAbstract, SubpassContents, }, - device::DeviceOwned, + device::{DeviceOwned, QueueFlags}, format::Format, image::SampleCount, query::{QueryControlFlags, QueryPipelineStatisticFlags, QueryType}, @@ -119,9 +119,9 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdExecuteCommands-commandBuffer-cmdpool - if !(queue_family_properties.queue_flags.transfer - || queue_family_properties.queue_flags.graphics - || queue_family_properties.queue_flags.compute) + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::TRANSFER | QueueFlags::GRAPHICS | QueueFlags::COMPUTE) { return Err(ExecuteCommandsError::NotSupportedByQueueFamily); } @@ -325,7 +325,7 @@ where // VUID-vkCmdExecuteCommands-commandBuffer-00101 if !self.query_state.is_empty() && !self.device().enabled_features().inherited_queries { 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 { features: &["inherited_queries"], ..Default::default() diff --git a/vulkano/src/command_buffer/commands/sync.rs b/vulkano/src/command_buffer/commands/sync.rs index b39113f9..fc58e745 100644 --- a/vulkano/src/command_buffer/commands/sync.rs +++ b/vulkano/src/command_buffer/commands/sync.rs @@ -126,8 +126,8 @@ impl UnsafeCommandBufferBuilder { _ne: _, } = barrier; - debug_assert!(src_stages.supported_access().contains(&src_access)); - debug_assert!(dst_stages.supported_access().contains(&dst_access)); + debug_assert!(src_stages.supported_access().contains(src_access)); + debug_assert!(dst_stages.supported_access().contains(dst_access)); ash::vk::MemoryBarrier2 { src_stage_mask: src_stages.into(), @@ -153,8 +153,8 @@ impl UnsafeCommandBufferBuilder { _ne: _, } = barrier; - debug_assert!(src_stages.supported_access().contains(&src_access)); - debug_assert!(dst_stages.supported_access().contains(&dst_access)); + debug_assert!(src_stages.supported_access().contains(src_access)); + debug_assert!(dst_stages.supported_access().contains(dst_access)); debug_assert!(!range.is_empty()); debug_assert!(range.end <= buffer.size()); @@ -195,8 +195,8 @@ impl UnsafeCommandBufferBuilder { _ne: _, } = barrier; - debug_assert!(src_stages.supported_access().contains(&src_access)); - debug_assert!(dst_stages.supported_access().contains(&dst_access)); + debug_assert!(src_stages.supported_access().contains(src_access)); + debug_assert!(dst_stages.supported_access().contains(dst_access)); debug_assert!(!matches!( new_layout, ImageLayout::Undefined | ImageLayout::Preinitialized @@ -205,7 +205,7 @@ impl UnsafeCommandBufferBuilder { .format() .unwrap() .aspects() - .contains(&subresource_range.aspects)); + .contains(subresource_range.aspects)); debug_assert!(!subresource_range.mip_levels.is_empty()); debug_assert!(subresource_range.mip_levels.end <= image.mip_levels()); debug_assert!(!subresource_range.array_layers.is_empty()); @@ -272,8 +272,8 @@ impl UnsafeCommandBufferBuilder { _ne: _, } = barrier; - debug_assert!(src_stages.supported_access().contains(&src_access)); - debug_assert!(dst_stages.supported_access().contains(&dst_access)); + debug_assert!(src_stages.supported_access().contains(src_access)); + debug_assert!(dst_stages.supported_access().contains(dst_access)); src_stage_mask |= src_stages.into(); dst_stage_mask |= dst_stages.into(); @@ -300,8 +300,8 @@ impl UnsafeCommandBufferBuilder { _ne: _, } = barrier; - debug_assert!(src_stages.supported_access().contains(&src_access)); - debug_assert!(dst_stages.supported_access().contains(&dst_access)); + debug_assert!(src_stages.supported_access().contains(src_access)); + debug_assert!(dst_stages.supported_access().contains(dst_access)); debug_assert!(!range.is_empty()); debug_assert!(range.end <= buffer.size()); @@ -343,8 +343,8 @@ impl UnsafeCommandBufferBuilder { _ne: _, } = barrier; - debug_assert!(src_stages.supported_access().contains(&src_access)); - debug_assert!(dst_stages.supported_access().contains(&dst_access)); + debug_assert!(src_stages.supported_access().contains(src_access)); + debug_assert!(dst_stages.supported_access().contains(dst_access)); debug_assert!(!matches!( new_layout, ImageLayout::Undefined | ImageLayout::Preinitialized @@ -353,7 +353,7 @@ impl UnsafeCommandBufferBuilder { .format() .unwrap() .aspects() - .contains(&subresource_range.aspects)); + .contains(subresource_range.aspects)); debug_assert!(!subresource_range.mip_levels.is_empty()); debug_assert!(subresource_range.mip_levels.end <= image.mip_levels()); debug_assert!(!subresource_range.array_layers.is_empty()); @@ -895,7 +895,7 @@ impl UnsafeCommandBufferBuilder { /// Calls `vkCmdResetEvent` on the builder. #[inline] 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()); let fns = self.device.fns(); diff --git a/vulkano/src/command_buffer/commands/transfer.rs b/vulkano/src/command_buffer/commands/transfer.rs index 3c6bc6c8..74022327 100644 --- a/vulkano/src/command_buffer/commands/transfer.rs +++ b/vulkano/src/command_buffer/commands/transfer.rs @@ -8,18 +8,18 @@ // according to those terms. use crate::{ - buffer::{BufferAccess, BufferContents, TypedBufferAccess}, + buffer::{BufferAccess, BufferContents, BufferUsage, TypedBufferAccess}, command_buffer::{ allocator::CommandBufferAllocator, synced::{Command, Resource, SyncCommandBufferBuilder, SyncCommandBufferBuilderError}, sys::UnsafeCommandBufferBuilder, AutoCommandBufferBuilder, CopyError, CopyErrorResource, }, - device::DeviceOwned, - format::Format, + device::{DeviceOwned, QueueFlags}, + format::{Format, FormatFeatures}, image::{ - ImageAccess, ImageAspects, ImageLayout, ImageSubresourceLayers, ImageType, SampleCount, - SampleCounts, + ImageAccess, ImageAspects, ImageLayout, ImageSubresourceLayers, ImageType, ImageUsage, + SampleCount, SampleCounts, }, sync::{AccessFlags, PipelineMemoryAccess, PipelineStages}, DeviceSize, SafeDeref, Version, VulkanObject, @@ -69,9 +69,9 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdCopyBuffer2-commandBuffer-cmdpool - if !(queue_family_properties.queue_flags.transfer - || queue_family_properties.queue_flags.graphics - || queue_family_properties.queue_flags.compute) + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::TRANSFER | QueueFlags::GRAPHICS | QueueFlags::COMPUTE) { return Err(CopyError::NotSupportedByQueueFamily); } @@ -91,7 +91,7 @@ where assert_eq!(device, dst_buffer.device()); // VUID-VkCopyBufferInfo2-srcBuffer-00118 - if !src_buffer.usage().transfer_src { + if !src_buffer.usage().intersects(BufferUsage::TRANSFER_SRC) { return Err(CopyError::MissingUsage { resource: CopyErrorResource::Source, usage: "transfer_src", @@ -99,7 +99,7 @@ where } // VUID-VkCopyBufferInfo2-dstBuffer-00120 - if !dst_buffer.usage().transfer_dst { + if !dst_buffer.usage().intersects(BufferUsage::TRANSFER_DST) { return Err(CopyError::MissingUsage { resource: CopyErrorResource::Destination, usage: "transfer_dst", @@ -216,9 +216,9 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdCopyImage2-commandBuffer-cmdpool - if !(queue_family_properties.queue_flags.transfer - || queue_family_properties.queue_flags.graphics - || queue_family_properties.queue_flags.compute) + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::TRANSFER | QueueFlags::GRAPHICS | QueueFlags::COMPUTE) { return Err(CopyError::NotSupportedByQueueFamily); } @@ -251,7 +251,10 @@ where if device.api_version() >= Version::V1_1 || device.enabled_extensions().khr_maintenance1 { // VUID-VkCopyImageInfo2-srcImage-01995 - if !src_image.format_features().transfer_src { + if !src_image + .format_features() + .intersects(FormatFeatures::TRANSFER_SRC) + { return Err(CopyError::MissingFormatFeature { resource: CopyErrorResource::Source, format_feature: "transfer_src", @@ -259,7 +262,10 @@ where } // VUID-VkCopyImageInfo2-dstImage-01996 - if !dst_image.format_features().transfer_dst { + if !dst_image + .format_features() + .intersects(FormatFeatures::TRANSFER_DST) + { return Err(CopyError::MissingFormatFeature { resource: CopyErrorResource::Destination, format_feature: "transfer_dst", @@ -275,7 +281,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-VkCopyImageInfo2-srcImage-01548 if src_image.format() != dst_image.format() { return Err(CopyError::FormatsMismatch { @@ -327,22 +335,28 @@ where }; Some(( - granularity(src_image.format().block_extent(), src_image_aspects.plane0), - granularity(dst_image.format().block_extent(), dst_image_aspects.plane0), + granularity( + src_image.format().block_extent(), + src_image_aspects.intersects(ImageAspects::PLANE_0), + ), + granularity( + dst_image.format().block_extent(), + dst_image_aspects.intersects(ImageAspects::PLANE_0), + ), )) } }; - if src_image_aspects.plane0 { + if src_image_aspects.intersects(ImageAspects::PLANE_0) { // VUID-VkCopyImageInfo2-srcImage-01552 // VUID-VkCopyImageInfo2-srcImage-01553 - src_image_aspects.color = false; + src_image_aspects -= ImageAspects::COLOR; } - if dst_image_aspects.plane0 { + if dst_image_aspects.intersects(ImageAspects::PLANE_0) { // VUID-VkCopyImageInfo2-dstImage-01554 // VUID-VkCopyImageInfo2-dstImage-01555 - dst_image_aspects.color = false; + dst_image_aspects -= ImageAspects::COLOR; } let mut src_image_aspects_used = ImageAspects::empty(); @@ -363,7 +377,7 @@ where let check_subresource = |resource: CopyErrorResource, image: &dyn ImageAccess, - image_aspects: &ImageAspects, + image_aspects: ImageAspects, subresource: &ImageSubresourceLayers| -> Result<_, CopyError> { // VUID-VkCopyImageInfo2-srcSubresource-01696 @@ -401,62 +415,63 @@ where // VUID-VkCopyImageInfo2-aspectMask-00142 // VUID-VkCopyImageInfo2-aspectMask-00143 - if !image_aspects.contains(&subresource.aspects) { + if !image_aspects.contains(subresource.aspects) { return Err(CopyError::AspectsNotAllowed { resource, region_index, aspects: subresource.aspects, - allowed_aspects: *image_aspects, + allowed_aspects: image_aspects, }); } - let (subresource_format, subresource_extent) = if image_aspects.plane0 { - // VUID-VkCopyImageInfo2-srcImage-01552 - // VUID-VkCopyImageInfo2-srcImage-01553 - // VUID-VkCopyImageInfo2-dstImage-01554 - // VUID-VkCopyImageInfo2-dstImage-01555 - if subresource.aspects.iter().count() != 1 { - return Err(CopyError::MultipleAspectsNotAllowed { - resource, - region_index, - aspects: subresource.aspects, - }); - } + let (subresource_format, subresource_extent) = + if image_aspects.intersects(ImageAspects::PLANE_0) { + // VUID-VkCopyImageInfo2-srcImage-01552 + // VUID-VkCopyImageInfo2-srcImage-01553 + // VUID-VkCopyImageInfo2-dstImage-01554 + // VUID-VkCopyImageInfo2-dstImage-01555 + if subresource.aspects.count() != 1 { + return Err(CopyError::MultipleAspectsNotAllowed { + resource, + region_index, + aspects: subresource.aspects, + }); + } - if subresource.aspects.plane0 { - ( - image.format().planes()[0], - image.dimensions().width_height_depth(), - ) - } else if subresource.aspects.plane1 { - ( - image.format().planes()[1], - image - .format() - .ycbcr_chroma_sampling() - .unwrap() - .subsampled_extent(image.dimensions().width_height_depth()), - ) + if subresource.aspects.intersects(ImageAspects::PLANE_0) { + ( + image.format().planes()[0], + image.dimensions().width_height_depth(), + ) + } else if subresource.aspects.intersects(ImageAspects::PLANE_1) { + ( + image.format().planes()[1], + image + .format() + .ycbcr_chroma_sampling() + .unwrap() + .subsampled_extent(image.dimensions().width_height_depth()), + ) + } else { + ( + image.format().planes()[2], + image + .format() + .ycbcr_chroma_sampling() + .unwrap() + .subsampled_extent(image.dimensions().width_height_depth()), + ) + } } else { ( - image.format().planes()[2], + image.format(), image - .format() - .ycbcr_chroma_sampling() + .dimensions() + .mip_level_dimensions(subresource.mip_level) .unwrap() - .subsampled_extent(image.dimensions().width_height_depth()), + .width_height_depth(), ) - } - } else { - ( - image.format(), - image - .dimensions() - .mip_level_dimensions(subresource.mip_level) - .unwrap() - .width_height_depth(), - ) - }; + }; Ok((subresource_format, subresource_extent)) }; @@ -467,17 +482,19 @@ where let (src_subresource_format, src_subresource_extent) = check_subresource( CopyErrorResource::Source, src_image, - &src_image_aspects, + src_image_aspects, src_subresource, )?; let (dst_subresource_format, dst_subresource_extent) = check_subresource( CopyErrorResource::Destination, dst_image, - &dst_image_aspects, + dst_image_aspects, dst_subresource, )?; - if !(src_image_aspects.plane0 || dst_image_aspects.plane0) { + if !(src_image_aspects.intersects(ImageAspects::PLANE_0) + || dst_image_aspects.intersects(ImageAspects::PLANE_0)) + { // VUID-VkCopyImageInfo2-srcImage-01551 if src_subresource.aspects != dst_subresource.aspects { return Err(CopyError::AspectsMismatch { @@ -663,7 +680,7 @@ where } = dst_region; // For a single-plane image, the aspects must always be identical anyway - if src_image_aspects.plane0 + if src_image_aspects.intersects(ImageAspects::PLANE_0) && src_subresource.aspects != dst_subresource.aspects { continue; @@ -777,7 +794,7 @@ where .. } = dst_region; - if src_image_aspects.plane0 + if src_image_aspects.intersects(ImageAspects::PLANE_0) && src_subresource.aspects != dst_subresource.aspects { continue; @@ -806,12 +823,8 @@ where } // VUID-VkCopyImageInfo2-aspect-06662 - if !(ImageAspects { - stencil: false, - ..src_image_aspects_used - }) - .is_empty() - && !src_image.usage().transfer_src + if !(src_image_aspects_used - ImageAspects::STENCIL).is_empty() + && !src_image.usage().intersects(ImageUsage::TRANSFER_SRC) { return Err(CopyError::MissingUsage { resource: CopyErrorResource::Source, @@ -820,12 +833,8 @@ where } // VUID-VkCopyImageInfo2-aspect-06663 - if !(ImageAspects { - stencil: false, - ..dst_image_aspects_used - }) - .is_empty() - && !dst_image.usage().transfer_dst + if !(dst_image_aspects_used - ImageAspects::STENCIL).is_empty() + && !dst_image.usage().intersects(ImageUsage::TRANSFER_DST) { return Err(CopyError::MissingUsage { resource: CopyErrorResource::Destination, @@ -834,7 +843,11 @@ where } // VUID-VkCopyImageInfo2-aspect-06664 - if src_image_aspects_used.stencil && !src_image.stencil_usage().transfer_src { + if src_image_aspects_used.intersects(ImageAspects::STENCIL) + && !src_image + .stencil_usage() + .intersects(ImageUsage::TRANSFER_SRC) + { return Err(CopyError::MissingUsage { resource: CopyErrorResource::Source, usage: "transfer_src", @@ -842,7 +855,11 @@ where } // VUID-VkCopyImageInfo2-aspect-06665 - if dst_image_aspects_used.stencil && !dst_image.stencil_usage().transfer_dst { + if dst_image_aspects_used.intersects(ImageAspects::STENCIL) + && !dst_image + .stencil_usage() + .intersects(ImageUsage::TRANSFER_DST) + { return Err(CopyError::MissingUsage { resource: CopyErrorResource::Destination, usage: "transfer_dst", @@ -901,9 +918,9 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdCopyBufferToImage2-commandBuffer-cmdpool - if !(queue_family_properties.queue_flags.transfer - || queue_family_properties.queue_flags.graphics - || queue_family_properties.queue_flags.compute) + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::TRANSFER | QueueFlags::GRAPHICS | QueueFlags::COMPUTE) { return Err(CopyError::NotSupportedByQueueFamily); } @@ -927,12 +944,16 @@ where let mut image_aspects = dst_image.format().aspects(); // VUID-VkCopyBufferToImageInfo2-commandBuffer-04477 - if !queue_family_properties.queue_flags.graphics && !image_aspects.color { + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS) + && !image_aspects.intersects(ImageAspects::COLOR) + { return Err(CopyError::DepthStencilNotSupportedByQueueFamily); } // VUID-VkCopyBufferToImageInfo2-srcBuffer-00174 - if !src_buffer.usage().transfer_src { + if !src_buffer.usage().intersects(BufferUsage::TRANSFER_SRC) { return Err(CopyError::MissingUsage { resource: CopyErrorResource::Source, usage: "transfer_src", @@ -940,7 +961,7 @@ where } // VUID-VkCopyBufferToImageInfo2-dstImage-00177 - if !dst_image.usage().transfer_dst { + if !dst_image.usage().intersects(ImageUsage::TRANSFER_DST) { return Err(CopyError::MissingUsage { resource: CopyErrorResource::Destination, usage: "transfer_dst", @@ -949,7 +970,10 @@ where if device.api_version() >= Version::V1_1 || device.enabled_extensions().khr_maintenance1 { // VUID-VkCopyBufferToImageInfo2-dstImage-01997 - if !dst_image.format_features().transfer_dst { + if !dst_image + .format_features() + .intersects(FormatFeatures::TRANSFER_DST) + { return Err(CopyError::MissingFormatFeature { resource: CopyErrorResource::Destination, format_feature: "transfer_dst", @@ -962,10 +986,7 @@ where return Err(CopyError::SampleCountInvalid { resource: CopyErrorResource::Destination, sample_count: dst_image.samples(), - allowed_sample_counts: SampleCounts { - sample1: true, - ..SampleCounts::empty() - }, + allowed_sample_counts: SampleCounts::SAMPLE_1, }); } @@ -1001,14 +1022,14 @@ where Some(granularity( dst_image.format().block_extent(), - image_aspects.plane0, + image_aspects.intersects(ImageAspects::PLANE_0), )) } }; - if image_aspects.plane0 { + if image_aspects.intersects(ImageAspects::PLANE_0) { // VUID-VkCopyBufferToImageInfo2-aspectMask-01560 - image_aspects.color = false; + image_aspects -= ImageAspects::COLOR; } for (region_index, region) in regions.iter().enumerate() { @@ -1051,7 +1072,7 @@ where assert!(!image_subresource.aspects.is_empty()); // VUID-VkCopyBufferToImageInfo2-aspectMask-00211 - if !image_aspects.contains(&image_subresource.aspects) { + if !image_aspects.contains(image_subresource.aspects) { return Err(CopyError::AspectsNotAllowed { resource: CopyErrorResource::Destination, region_index, @@ -1062,7 +1083,7 @@ where // VUID-VkBufferImageCopy2-aspectMask-00212 // VUID-VkCopyBufferToImageInfo2-aspectMask-01560 - if image_subresource.aspects.iter().count() != 1 { + if image_subresource.aspects.count() != 1 { return Err(CopyError::MultipleAspectsNotAllowed { resource: CopyErrorResource::Destination, region_index, @@ -1070,41 +1091,42 @@ where }); } - let (image_subresource_format, image_subresource_extent) = if image_aspects.plane0 { - if image_subresource.aspects.plane0 { - ( - dst_image.format().planes()[0], - dst_image.dimensions().width_height_depth(), - ) - } else if image_subresource.aspects.plane1 { - ( - dst_image.format().planes()[1], - dst_image - .format() - .ycbcr_chroma_sampling() - .unwrap() - .subsampled_extent(dst_image.dimensions().width_height_depth()), - ) + let (image_subresource_format, image_subresource_extent) = + if image_aspects.intersects(ImageAspects::PLANE_0) { + if image_subresource.aspects.intersects(ImageAspects::PLANE_0) { + ( + dst_image.format().planes()[0], + dst_image.dimensions().width_height_depth(), + ) + } else if image_subresource.aspects.intersects(ImageAspects::PLANE_1) { + ( + dst_image.format().planes()[1], + dst_image + .format() + .ycbcr_chroma_sampling() + .unwrap() + .subsampled_extent(dst_image.dimensions().width_height_depth()), + ) + } else { + ( + dst_image.format().planes()[2], + dst_image + .format() + .ycbcr_chroma_sampling() + .unwrap() + .subsampled_extent(dst_image.dimensions().width_height_depth()), + ) + } } else { ( - dst_image.format().planes()[2], + dst_image.format(), dst_image - .format() - .ycbcr_chroma_sampling() + .dimensions() + .mip_level_dimensions(image_subresource.mip_level) .unwrap() - .subsampled_extent(dst_image.dimensions().width_height_depth()), + .width_height_depth(), ) - } - } else { - ( - dst_image.format(), - dst_image - .dimensions() - .mip_level_dimensions(image_subresource.mip_level) - .unwrap() - .width_height_depth(), - ) - }; + }; if let Some(extent_alignment) = extent_alignment { for i in 0..3 { @@ -1222,20 +1244,21 @@ where } // https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkBufferImageCopy.html#_description - let image_subresource_block_size = if image_subresource.aspects.stencil { - 1 - } else if image_subresource.aspects.depth { - match image_subresource_format { - Format::D16_UNORM | Format::D16_UNORM_S8_UINT => 2, - Format::D32_SFLOAT - | Format::D32_SFLOAT_S8_UINT - | Format::X8_D24_UNORM_PACK32 - | Format::D24_UNORM_S8_UINT => 4, - _ => unreachable!(), - } - } else { - image_subresource_format.block_size().unwrap() - }; + let image_subresource_block_size = + if image_subresource.aspects.intersects(ImageAspects::STENCIL) { + 1 + } else if image_subresource.aspects.intersects(ImageAspects::DEPTH) { + match image_subresource_format { + Format::D16_UNORM | Format::D16_UNORM_S8_UINT => 2, + Format::D32_SFLOAT + | Format::D32_SFLOAT_S8_UINT + | Format::X8_D24_UNORM_PACK32 + | Format::D24_UNORM_S8_UINT => 4, + _ => unreachable!(), + } + } else { + image_subresource_format.block_size().unwrap() + }; // VUID-VkCopyBufferToImageInfo2-pRegions-04725 // VUID-VkCopyBufferToImageInfo2-pRegions-04726 @@ -1250,27 +1273,29 @@ where }); } - let buffer_offset_alignment = if image_aspects.depth || image_aspects.stencil { - 4 - } else { - let mut buffer_offset_alignment = image_subresource_block_size; + let buffer_offset_alignment = + if image_aspects.intersects(ImageAspects::DEPTH | ImageAspects::STENCIL) { + 4 + } else { + let mut buffer_offset_alignment = image_subresource_block_size; - // VUID-VkCopyBufferToImageInfo2-commandBuffer-04052 - // Make the alignment a multiple of 4. - if !(queue_family_properties.queue_flags.graphics - || queue_family_properties.queue_flags.compute) - { - if buffer_offset_alignment % 2 != 0 { - buffer_offset_alignment *= 2; + // VUID-VkCopyBufferToImageInfo2-commandBuffer-04052 + // Make the alignment a multiple of 4. + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS | QueueFlags::COMPUTE) + { + if buffer_offset_alignment % 2 != 0 { + buffer_offset_alignment *= 2; + } + + if buffer_offset_alignment % 4 != 0 { + buffer_offset_alignment *= 2; + } } - if buffer_offset_alignment % 4 != 0 { - buffer_offset_alignment *= 2; - } - } - - buffer_offset_alignment - }; + buffer_offset_alignment + }; // VUID-VkCopyBufferToImageInfo2-bufferOffset-00206 // VUID-VkCopyBufferToImageInfo2-bufferOffset-01558 @@ -1332,9 +1357,9 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdCopyImageToBuffer2-commandBuffer-cmdpool - if !(queue_family_properties.queue_flags.transfer - || queue_family_properties.queue_flags.graphics - || queue_family_properties.queue_flags.compute) + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::TRANSFER | QueueFlags::GRAPHICS | QueueFlags::COMPUTE) { return Err(CopyError::NotSupportedByQueueFamily); } @@ -1358,7 +1383,7 @@ where let mut image_aspects = src_image.format().aspects(); // VUID-VkCopyImageToBufferInfo2-srcImage-00186 - if !src_image.usage().transfer_src { + if !src_image.usage().intersects(ImageUsage::TRANSFER_SRC) { return Err(CopyError::MissingUsage { resource: CopyErrorResource::Source, usage: "transfer_src", @@ -1366,7 +1391,7 @@ where } // VUID-VkCopyImageToBufferInfo2-dstBuffer-00191 - if !dst_buffer.usage().transfer_dst { + if !dst_buffer.usage().intersects(BufferUsage::TRANSFER_DST) { return Err(CopyError::MissingUsage { resource: CopyErrorResource::Destination, usage: "transfer_dst", @@ -1375,7 +1400,10 @@ where if device.api_version() >= Version::V1_1 || device.enabled_extensions().khr_maintenance1 { // VUID-VkCopyImageToBufferInfo2-srcImage-01998 - if !src_image.format_features().transfer_src { + if !src_image + .format_features() + .intersects(FormatFeatures::TRANSFER_SRC) + { return Err(CopyError::MissingFormatFeature { resource: CopyErrorResource::Source, format_feature: "transfer_src", @@ -1388,10 +1416,7 @@ where return Err(CopyError::SampleCountInvalid { resource: CopyErrorResource::Source, sample_count: src_image.samples(), - allowed_sample_counts: SampleCounts { - sample1: true, - ..SampleCounts::empty() - }, + allowed_sample_counts: SampleCounts::SAMPLE_1, }); } @@ -1427,14 +1452,14 @@ where Some(granularity( src_image.format().block_extent(), - image_aspects.plane0, + image_aspects.intersects(ImageAspects::PLANE_0), )) } }; - if image_aspects.plane0 { + if image_aspects.intersects(ImageAspects::PLANE_0) { // VUID-VkCopyImageToBufferInfo2-aspectMask-01560 - image_aspects.color = false; + image_aspects -= ImageAspects::COLOR; } for (region_index, region) in regions.iter().enumerate() { @@ -1476,7 +1501,7 @@ where assert!(!image_subresource.aspects.is_empty()); // VUID-VkCopyImageToBufferInfo2-aspectMask-00211 - if !image_aspects.contains(&image_subresource.aspects) { + if !image_aspects.contains(image_subresource.aspects) { return Err(CopyError::AspectsNotAllowed { resource: CopyErrorResource::Source, region_index, @@ -1486,7 +1511,7 @@ where } // VUID-VkBufferImageCopy2-aspectMask-00212 - if image_subresource.aspects.iter().count() != 1 { + if image_subresource.aspects.count() != 1 { return Err(CopyError::MultipleAspectsNotAllowed { resource: CopyErrorResource::Source, region_index, @@ -1494,41 +1519,42 @@ where }); } - let (image_subresource_format, image_subresource_extent) = if image_aspects.plane0 { - if image_subresource.aspects.plane0 { - ( - src_image.format().planes()[0], - src_image.dimensions().width_height_depth(), - ) - } else if image_subresource.aspects.plane1 { - ( - src_image.format().planes()[1], - src_image - .format() - .ycbcr_chroma_sampling() - .unwrap() - .subsampled_extent(src_image.dimensions().width_height_depth()), - ) + let (image_subresource_format, image_subresource_extent) = + if image_aspects.intersects(ImageAspects::PLANE_0) { + if image_subresource.aspects.intersects(ImageAspects::PLANE_0) { + ( + src_image.format().planes()[0], + src_image.dimensions().width_height_depth(), + ) + } else if image_subresource.aspects.intersects(ImageAspects::PLANE_1) { + ( + src_image.format().planes()[1], + src_image + .format() + .ycbcr_chroma_sampling() + .unwrap() + .subsampled_extent(src_image.dimensions().width_height_depth()), + ) + } else { + ( + src_image.format().planes()[2], + src_image + .format() + .ycbcr_chroma_sampling() + .unwrap() + .subsampled_extent(src_image.dimensions().width_height_depth()), + ) + } } else { ( - src_image.format().planes()[2], + src_image.format(), src_image - .format() - .ycbcr_chroma_sampling() + .dimensions() + .mip_level_dimensions(image_subresource.mip_level) .unwrap() - .subsampled_extent(src_image.dimensions().width_height_depth()), + .width_height_depth(), ) - } - } else { - ( - src_image.format(), - src_image - .dimensions() - .mip_level_dimensions(image_subresource.mip_level) - .unwrap() - .width_height_depth(), - ) - }; + }; if let Some(extent_alignment) = extent_alignment { for i in 0..3 { @@ -1646,20 +1672,21 @@ where } // https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkBufferImageCopy.html#_description - let image_subresource_block_size = if image_subresource.aspects.stencil { - 1 - } else if image_subresource.aspects.depth { - match image_subresource_format { - Format::D16_UNORM | Format::D16_UNORM_S8_UINT => 2, - Format::D32_SFLOAT - | Format::D32_SFLOAT_S8_UINT - | Format::X8_D24_UNORM_PACK32 - | Format::D24_UNORM_S8_UINT => 4, - _ => unreachable!(), - } - } else { - image_subresource_format.block_size().unwrap() - }; + let image_subresource_block_size = + if image_subresource.aspects.intersects(ImageAspects::STENCIL) { + 1 + } else if image_subresource.aspects.intersects(ImageAspects::DEPTH) { + match image_subresource_format { + Format::D16_UNORM | Format::D16_UNORM_S8_UINT => 2, + Format::D32_SFLOAT + | Format::D32_SFLOAT_S8_UINT + | Format::X8_D24_UNORM_PACK32 + | Format::D24_UNORM_S8_UINT => 4, + _ => unreachable!(), + } + } else { + image_subresource_format.block_size().unwrap() + }; // VUID-VkCopyImageToBufferInfo2-pRegions-04725 // VUID-VkCopyImageToBufferInfo2-pRegions-04726 @@ -1674,27 +1701,29 @@ where }); } - let buffer_offset_alignment = if image_aspects.depth || image_aspects.stencil { - 4 - } else { - let mut buffer_offset_alignment = image_subresource_block_size; + let buffer_offset_alignment = + if image_aspects.intersects(ImageAspects::DEPTH | ImageAspects::STENCIL) { + 4 + } else { + let mut buffer_offset_alignment = image_subresource_block_size; - // VUID-VkCopyImageToBufferInfo2-commandBuffer-04052 - // Make the alignment a multiple of 4. - if !(queue_family_properties.queue_flags.graphics - || queue_family_properties.queue_flags.compute) - { - if buffer_offset_alignment % 2 != 0 { - buffer_offset_alignment *= 2; + // VUID-VkCopyImageToBufferInfo2-commandBuffer-04052 + // Make the alignment a multiple of 4. + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS | QueueFlags::COMPUTE) + { + if buffer_offset_alignment % 2 != 0 { + buffer_offset_alignment *= 2; + } + + if buffer_offset_alignment % 4 != 0 { + buffer_offset_alignment *= 2; + } } - if buffer_offset_alignment % 4 != 0 { - buffer_offset_alignment *= 2; - } - } - - buffer_offset_alignment - }; + buffer_offset_alignment + }; // VUID-VkCopyImageToBufferInfo2-bufferOffset-01558 // VUID-VkCopyImageToBufferInfo2-bufferOffset-01559 @@ -1761,16 +1790,17 @@ where if device.api_version() >= Version::V1_1 || device.enabled_extensions().khr_maintenance1 { // VUID-vkCmdFillBuffer-commandBuffer-cmdpool - if !(queue_family_properties.queue_flags.transfer - || queue_family_properties.queue_flags.graphics - || queue_family_properties.queue_flags.compute) + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::TRANSFER | QueueFlags::GRAPHICS | QueueFlags::COMPUTE) { return Err(CopyError::NotSupportedByQueueFamily); } } else { // VUID-vkCmdFillBuffer-commandBuffer-00030 - if !(queue_family_properties.queue_flags.graphics - || queue_family_properties.queue_flags.compute) + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::GRAPHICS | QueueFlags::COMPUTE) { return Err(CopyError::NotSupportedByQueueFamily); } @@ -1793,7 +1823,7 @@ where assert!(size != 0); // VUID-vkCmdFillBuffer-dstBuffer-00029 - if !dst_buffer.usage().transfer_dst { + if !dst_buffer.usage().intersects(BufferUsage::TRANSFER_DST) { return Err(CopyError::MissingUsage { resource: CopyErrorResource::Destination, usage: "transfer_dst", @@ -1878,9 +1908,9 @@ where let queue_family_properties = self.queue_family_properties(); // VUID-vkCmdUpdateBuffer-commandBuffer-cmdpool - if !(queue_family_properties.queue_flags.transfer - || queue_family_properties.queue_flags.graphics - || queue_family_properties.queue_flags.compute) + if !queue_family_properties + .queue_flags + .intersects(QueueFlags::TRANSFER | QueueFlags::GRAPHICS | QueueFlags::COMPUTE) { return Err(CopyError::NotSupportedByQueueFamily); } @@ -1894,7 +1924,7 @@ where assert!(size_of_val(data) != 0); // VUID-vkCmdUpdateBuffer-dstBuffer-00034 - if !dst_buffer.usage().transfer_dst { + if !dst_buffer.usage().intersects(BufferUsage::TRANSFER_DST) { return Err(CopyError::MissingUsage { resource: CopyErrorResource::Destination, usage: "transfer_dst", @@ -1992,14 +2022,8 @@ impl SyncCommandBufferBuilder { buffer: src_buffer.clone(), range: src_offset..src_offset + size, memory: PipelineMemoryAccess { - stages: PipelineStages { - all_transfer: true, - ..PipelineStages::empty() - }, - access: AccessFlags { - transfer_read: true, - ..AccessFlags::empty() - }, + stages: PipelineStages::ALL_TRANSFER, + access: AccessFlags::TRANSFER_READ, exclusive: false, }, }, @@ -2010,14 +2034,8 @@ impl SyncCommandBufferBuilder { buffer: dst_buffer.clone(), range: dst_offset..dst_offset + size, memory: PipelineMemoryAccess { - stages: PipelineStages { - all_transfer: true, - ..PipelineStages::empty() - }, - access: AccessFlags { - transfer_write: true, - ..AccessFlags::empty() - }, + stages: PipelineStages::ALL_TRANSFER, + access: AccessFlags::TRANSFER_WRITE, exclusive: true, }, }, @@ -2090,14 +2108,8 @@ impl SyncCommandBufferBuilder { image: src_image.clone(), subresource_range: src_subresource.clone().into(), memory: PipelineMemoryAccess { - stages: PipelineStages { - all_transfer: true, - ..PipelineStages::empty() - }, - access: AccessFlags { - transfer_read: true, - ..AccessFlags::empty() - }, + stages: PipelineStages::ALL_TRANSFER, + access: AccessFlags::TRANSFER_READ, exclusive: false, }, start_layout: src_image_layout, @@ -2110,14 +2122,8 @@ impl SyncCommandBufferBuilder { image: dst_image.clone(), subresource_range: dst_subresource.clone().into(), memory: PipelineMemoryAccess { - stages: PipelineStages { - all_transfer: true, - ..PipelineStages::empty() - }, - access: AccessFlags { - transfer_write: true, - ..AccessFlags::empty() - }, + stages: PipelineStages::ALL_TRANSFER, + access: AccessFlags::TRANSFER_WRITE, exclusive: true, }, start_layout: dst_image_layout, @@ -2193,14 +2199,8 @@ impl SyncCommandBufferBuilder { range: buffer_offset ..buffer_offset + region.buffer_copy_size(dst_image.format()), memory: PipelineMemoryAccess { - stages: PipelineStages { - all_transfer: true, - ..PipelineStages::empty() - }, - access: AccessFlags { - transfer_read: true, - ..AccessFlags::empty() - }, + stages: PipelineStages::ALL_TRANSFER, + access: AccessFlags::TRANSFER_READ, exclusive: false, }, }, @@ -2211,14 +2211,8 @@ impl SyncCommandBufferBuilder { image: dst_image.clone(), subresource_range: image_subresource.clone().into(), memory: PipelineMemoryAccess { - stages: PipelineStages { - all_transfer: true, - ..PipelineStages::empty() - }, - access: AccessFlags { - transfer_write: true, - ..AccessFlags::empty() - }, + stages: PipelineStages::ALL_TRANSFER, + access: AccessFlags::TRANSFER_WRITE, exclusive: true, }, start_layout: dst_image_layout, @@ -2295,14 +2289,8 @@ impl SyncCommandBufferBuilder { image: src_image.clone(), subresource_range: image_subresource.clone().into(), memory: PipelineMemoryAccess { - stages: PipelineStages { - all_transfer: true, - ..PipelineStages::empty() - }, - access: AccessFlags { - transfer_read: true, - ..AccessFlags::empty() - }, + stages: PipelineStages::ALL_TRANSFER, + access: AccessFlags::TRANSFER_READ, exclusive: false, }, start_layout: src_image_layout, @@ -2316,14 +2304,8 @@ impl SyncCommandBufferBuilder { range: buffer_offset ..buffer_offset + region.buffer_copy_size(src_image.format()), memory: PipelineMemoryAccess { - stages: PipelineStages { - all_transfer: true, - ..PipelineStages::empty() - }, - access: AccessFlags { - transfer_write: true, - ..AccessFlags::empty() - }, + stages: PipelineStages::ALL_TRANSFER, + access: AccessFlags::TRANSFER_WRITE, exclusive: true, }, }, @@ -2381,14 +2363,8 @@ impl SyncCommandBufferBuilder { buffer: dst_buffer.clone(), range: dst_offset..dst_offset + size, memory: PipelineMemoryAccess { - stages: PipelineStages { - all_transfer: true, - ..PipelineStages::empty() - }, - access: AccessFlags { - transfer_write: true, - ..AccessFlags::empty() - }, + stages: PipelineStages::ALL_TRANSFER, + access: AccessFlags::TRANSFER_WRITE, exclusive: true, }, }, @@ -2444,14 +2420,8 @@ impl SyncCommandBufferBuilder { buffer: dst_buffer.clone(), range: dst_offset..dst_offset + size_of_val(data.deref()) as DeviceSize, memory: PipelineMemoryAccess { - stages: PipelineStages { - all_transfer: true, - ..PipelineStages::empty() - }, - access: AccessFlags { - transfer_write: true, - ..AccessFlags::empty() - }, + stages: PipelineStages::ALL_TRANSFER, + access: AccessFlags::TRANSFER_WRITE, exclusive: true, }, }, @@ -3521,9 +3491,9 @@ impl BufferImageCopy { let num_blocks = blocks_to_last_slice + blocks_to_last_row + image_extent[0] as DeviceSize; // https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkBufferImageCopy.html#_description - let block_size = if image_subresource.aspects.stencil { + let block_size = if image_subresource.aspects.intersects(ImageAspects::STENCIL) { 1 - } else if image_subresource.aspects.depth { + } else if image_subresource.aspects.intersects(ImageAspects::DEPTH) { match format { Format::D16_UNORM | Format::D16_UNORM_S8_UINT => 2, Format::D32_SFLOAT diff --git a/vulkano/src/command_buffer/mod.rs b/vulkano/src/command_buffer/mod.rs index ebdbecc8..b81d1cc4 100644 --- a/vulkano/src/command_buffer/mod.rs +++ b/vulkano/src/command_buffer/mod.rs @@ -169,8 +169,9 @@ pub struct DispatchIndirectCommand { } vulkan_enum! { - /// Describes what a subpass in a command buffer will contain. #[non_exhaustive] + + /// Describes what a subpass in a command buffer will contain. SubpassContents = SubpassContents(i32); /// 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 /// when this secondary command buffer is executed. /// - /// The `pipeline_statistics_query` feature must be enabled if any of the flags of this value - /// are set. + /// If this value is not empty, the [`pipeline_statistics_query`] feature must be enabled on + /// the device. /// /// The default value is [`QueryPipelineStatisticFlags::empty()`]. + /// + /// [`pipeline_statistics_query`]: crate::device::Features::pipeline_statistics_query pub query_statistics_flags: QueryPipelineStatisticFlags, 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 /// 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 - /// must be enabled on the device. + /// If set to a nonzero value, then the [`multiview`] feature must be enabled on the device. /// /// The default value is `0`. + /// + /// [`multiview`]: crate::device::Features::multiview pub view_mask: u32, /// 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 /// scope: stages of queue operations preceding the signal operation that must complete before /// the semaphore is signalled. - /// If not set to `all_commands` only, the - /// [`synchronization2`](crate::device::Features::synchronization2) feature must be enabled - /// on the device. + /// If this value does not equal [`ALL_COMMANDS`], then the [`synchronization2`] feature must + /// be enabled 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 _ne: crate::NonExhaustive, @@ -465,10 +471,7 @@ impl SemaphoreSubmitInfo { pub fn semaphore(semaphore: Arc) -> Self { Self { semaphore, - stages: PipelineStages { - all_commands: true, - ..PipelineStages::empty() - }, + stages: PipelineStages::ALL_COMMANDS, _ne: crate::NonExhaustive(()), } } diff --git a/vulkano/src/command_buffer/pool.rs b/vulkano/src/command_buffer/pool.rs index aa17c0d2..225cdbfe 100644 --- a/vulkano/src/command_buffer/pool.rs +++ b/vulkano/src/command_buffer/pool.rs @@ -276,7 +276,7 @@ impl CommandPool { || self.device.enabled_extensions().khr_maintenance1) { return Err(CommandPoolTrimError::RequirementNotMet { - required_for: "`trim`", + required_for: "`CommandPool::trim`", requires_one_of: RequiresOneOf { api_version: Some(Version::V1_1), device_extensions: &["khr_maintenance1"], diff --git a/vulkano/src/command_buffer/synced/builder.rs b/vulkano/src/command_buffer/synced/builder.rs index 2f5bcf41..fe45dd26 100644 --- a/vulkano/src/command_buffer/synced/builder.rs +++ b/vulkano/src/command_buffer/synced/builder.rs @@ -205,7 +205,7 @@ impl SyncCommandBufferBuilder { ref range, 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) = self.find_buffer_conflict(buffer, range.clone(), memory) @@ -226,7 +226,7 @@ impl SyncCommandBufferBuilder { 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::Preinitialized); @@ -453,24 +453,10 @@ impl SyncCommandBufferBuilder { // will come before them, it's the only thing that works for now. // TODO: come up with something better let barrier = BufferMemoryBarrier { - src_stages: PipelineStages { - all_commands: true, - ..PipelineStages::empty() - }, - 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() - }, + src_stages: PipelineStages::ALL_COMMANDS, + src_access: AccessFlags::MEMORY_READ | AccessFlags::MEMORY_WRITE, + dst_stages: PipelineStages::ALL_COMMANDS, + dst_access: AccessFlags::MEMORY_READ | AccessFlags::MEMORY_WRITE, range: range.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. // TODO: come up with something better let mut barrier = ImageMemoryBarrier { - src_stages: PipelineStages { - all_commands: true, - ..PipelineStages::empty() - }, - 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() - }, + src_stages: PipelineStages::ALL_COMMANDS, + src_access: AccessFlags::MEMORY_READ | AccessFlags::MEMORY_WRITE, + dst_stages: PipelineStages::ALL_COMMANDS, + dst_access: AccessFlags::MEMORY_READ | AccessFlags::MEMORY_WRITE, old_layout: state.initial_layout, new_layout: state.initial_layout, subresource_range: inner.image.range_to_subresources(range.clone()), @@ -812,10 +784,7 @@ impl SyncCommandBufferBuilder { .push(ImageMemoryBarrier { src_stages: state.memory.stages, src_access: state.memory.access, - dst_stages: PipelineStages { - top_of_pipe: true, - ..PipelineStages::empty() - }, + dst_stages: PipelineStages::TOP_OF_PIPE, dst_access: AccessFlags::empty(), old_layout: state.current_layout, new_layout: state.final_layout, diff --git a/vulkano/src/command_buffer/synced/mod.rs b/vulkano/src/command_buffer/synced/mod.rs index 7bbaad56..d17d3fb2 100644 --- a/vulkano/src/command_buffer/synced/mod.rs +++ b/vulkano/src/command_buffer/synced/mod.rs @@ -427,10 +427,7 @@ mod tests { let buffer = DeviceLocalBuffer::from_data( &memory_allocator, 0u32, - BufferUsage { - transfer_dst: true, - ..BufferUsage::empty() - }, + BufferUsage::TRANSFER_DST, &mut cbb, ) .unwrap(); @@ -542,10 +539,7 @@ mod tests { let memory_allocator = StandardMemoryAllocator::new_default(device); let buf = CpuAccessibleBuffer::from_data( &memory_allocator, - BufferUsage { - vertex_buffer: true, - ..BufferUsage::empty() - }, + BufferUsage::VERTEX_BUFFER, false, 0u32, ) diff --git a/vulkano/src/command_buffer/sys.rs b/vulkano/src/command_buffer/sys.rs index 0e6b96c4..b0ac663f 100644 --- a/vulkano/src/command_buffer/sys.rs +++ b/vulkano/src/command_buffer/sys.rs @@ -20,6 +20,7 @@ use crate::{ CommandBufferInheritanceRenderingInfo, }, device::{Device, DeviceOwned}, + query::QueryControlFlags, OomError, VulkanError, VulkanObject, }; use smallvec::SmallVec; @@ -104,7 +105,7 @@ impl UnsafeCommandBufferBuilder { if let Some(flags) = occlusion_query { 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; } } diff --git a/vulkano/src/command_buffer/traits.rs b/vulkano/src/command_buffer/traits.rs index afa33384..58f46bbc 100644 --- a/vulkano/src/command_buffer/traits.rs +++ b/vulkano/src/command_buffer/traits.rs @@ -335,11 +335,8 @@ where .into_iter() .map(|semaphore| { SemaphoreSubmitInfo { - stages: PipelineStages { - // TODO: correct stages ; hard - all_commands: true, - ..PipelineStages::empty() - }, + // TODO: correct stages ; hard + stages: PipelineStages::ALL_COMMANDS, ..SemaphoreSubmitInfo::semaphore(semaphore) } }) diff --git a/vulkano/src/descriptor_set/layout.rs b/vulkano/src/descriptor_set/layout.rs index 64693b41..8bbfe3a5 100644 --- a/vulkano/src/descriptor_set/layout.rs +++ b/vulkano/src/descriptor_set/layout.rs @@ -221,7 +221,8 @@ impl DescriptorSetLayout { .descriptor_binding_variable_descriptor_count { 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 { features: &["descriptor_binding_variable_descriptor_count"], ..Default::default() @@ -756,7 +757,7 @@ impl DescriptorSetLayoutBinding { } } - if !self.stages.contains(&stages) { + if !self.stages.contains(stages) { return Err(DescriptorRequirementsNotMet::ShaderStages { required: stages, obtained: self.stages, @@ -824,8 +825,9 @@ impl Display for DescriptorRequirementsNotMet { } vulkan_enum! { - /// Describes what kind of resource may later be bound to a descriptor. #[non_exhaustive] + + /// Describes what kind of resource may later be bound to a descriptor. DescriptorType = DescriptorType(i32); /// Describes how a `SampledImage` descriptor should be read. diff --git a/vulkano/src/descriptor_set/update.rs b/vulkano/src/descriptor_set/update.rs index 6e54abbc..c4aa6b1a 100644 --- a/vulkano/src/descriptor_set/update.rs +++ b/vulkano/src/descriptor_set/update.rs @@ -9,9 +9,9 @@ use super::layout::{DescriptorSetLayout, DescriptorSetLayoutBinding, DescriptorType}; use crate::{ - buffer::{view::BufferViewAbstract, BufferAccess, BufferInner}, + buffer::{view::BufferViewAbstract, BufferAccess, BufferInner, BufferUsage}, device::DeviceOwned, - image::{view::ImageViewType, ImageType, ImageViewAbstract}, + image::{view::ImageViewType, ImageAspects, ImageType, ImageUsage, ImageViewAbstract}, sampler::{Sampler, SamplerImageViewIncompatibleError}, DeviceSize, RequiresOneOf, VulkanObject, }; @@ -425,7 +425,7 @@ pub(crate) fn check_descriptor_write<'a>( for (index, buffer) in elements.iter().enumerate() { assert_eq!(device, buffer.device()); - if !buffer.inner().buffer.usage().storage_buffer { + if !buffer.usage().intersects(BufferUsage::STORAGE_BUFFER) { return Err(DescriptorSetUpdateError::MissingUsage { binding: write.binding(), 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() { assert_eq!(device, buffer.device()); - if !buffer.inner().buffer.usage().uniform_buffer { + if !buffer.usage().intersects(BufferUsage::UNIFORM_BUFFER) { return Err(DescriptorSetUpdateError::MissingUsage { binding: write.binding(), index: descriptor_range_start + index as u32, @@ -474,10 +474,8 @@ pub(crate) fn check_descriptor_write<'a>( // TODO: storage_texel_buffer_atomic if !buffer_view .buffer() - .inner() - .buffer .usage() - .storage_texel_buffer + .intersects(BufferUsage::STORAGE_TEXEL_BUFFER) { return Err(DescriptorSetUpdateError::MissingUsage { binding: write.binding(), @@ -493,10 +491,8 @@ pub(crate) fn check_descriptor_write<'a>( if !buffer_view .buffer() - .inner() - .buffer .usage() - .uniform_texel_buffer + .intersects(BufferUsage::UNIFORM_TEXEL_BUFFER) { return Err(DescriptorSetUpdateError::MissingUsage { binding: write.binding(), @@ -526,7 +522,7 @@ pub(crate) fn check_descriptor_write<'a>( assert_eq!(device, image_view.device()); // VUID-VkWriteDescriptorSet-descriptorType-00337 - if !image_view.usage().sampled { + if !image_view.usage().intersects(ImageUsage::SAMPLED) { return Err(DescriptorSetUpdateError::MissingUsage { binding: write.binding(), index: descriptor_range_start + index as u32, @@ -548,8 +544,10 @@ pub(crate) fn check_descriptor_write<'a>( } // VUID-VkDescriptorImageInfo-imageView-01976 - if image_view.subresource_range().aspects.depth - && image_view.subresource_range().aspects.stencil + if image_view + .subresource_range() + .aspects + .contains(ImageAspects::DEPTH | ImageAspects::STENCIL) { return Err(DescriptorSetUpdateError::ImageViewDepthAndStencil { binding: write.binding(), @@ -571,7 +569,7 @@ pub(crate) fn check_descriptor_write<'a>( assert_eq!(device, image_view.device()); // VUID-VkWriteDescriptorSet-descriptorType-00337 - if !image_view.usage().sampled { + if !image_view.usage().intersects(ImageUsage::SAMPLED) { return Err(DescriptorSetUpdateError::MissingUsage { binding: write.binding(), index: descriptor_range_start + index as u32, @@ -593,8 +591,10 @@ pub(crate) fn check_descriptor_write<'a>( } // VUID-VkDescriptorImageInfo-imageView-01976 - if image_view.subresource_range().aspects.depth - && image_view.subresource_range().aspects.stencil + if image_view + .subresource_range() + .aspects + .contains(ImageAspects::DEPTH | ImageAspects::STENCIL) { return Err(DescriptorSetUpdateError::ImageViewDepthAndStencil { binding: write.binding(), @@ -618,7 +618,7 @@ pub(crate) fn check_descriptor_write<'a>( assert_eq!(device, image_view.device()); // VUID-VkWriteDescriptorSet-descriptorType-00339 - if !image_view.usage().storage { + if !image_view.usage().intersects(ImageUsage::STORAGE) { return Err(DescriptorSetUpdateError::MissingUsage { binding: write.binding(), index: descriptor_range_start + index as u32, @@ -640,8 +640,10 @@ pub(crate) fn check_descriptor_write<'a>( } // VUID-VkDescriptorImageInfo-imageView-01976 - if image_view.subresource_range().aspects.depth - && image_view.subresource_range().aspects.stencil + if image_view + .subresource_range() + .aspects + .contains(ImageAspects::DEPTH | ImageAspects::STENCIL) { return Err(DescriptorSetUpdateError::ImageViewDepthAndStencil { binding: write.binding(), @@ -673,7 +675,7 @@ pub(crate) fn check_descriptor_write<'a>( assert_eq!(device, image_view.device()); // VUID-VkWriteDescriptorSet-descriptorType-00338 - if !image_view.usage().input_attachment { + if !image_view.usage().intersects(ImageUsage::INPUT_ATTACHMENT) { return Err(DescriptorSetUpdateError::MissingUsage { binding: write.binding(), index: descriptor_range_start + index as u32, @@ -695,8 +697,10 @@ pub(crate) fn check_descriptor_write<'a>( } // VUID-VkDescriptorImageInfo-imageView-01976 - if image_view.subresource_range().aspects.depth - && image_view.subresource_range().aspects.stencil + if image_view + .subresource_range() + .aspects + .contains(ImageAspects::DEPTH | ImageAspects::STENCIL) { return Err(DescriptorSetUpdateError::ImageViewDepthAndStencil { binding: write.binding(), @@ -752,7 +756,7 @@ pub(crate) fn check_descriptor_write<'a>( assert_eq!(device, sampler.device()); // VUID-VkWriteDescriptorSet-descriptorType-00337 - if !image_view.usage().sampled { + if !image_view.usage().intersects(ImageUsage::SAMPLED) { return Err(DescriptorSetUpdateError::MissingUsage { binding: write.binding(), index: descriptor_range_start + index as u32, @@ -774,8 +778,10 @@ pub(crate) fn check_descriptor_write<'a>( } // VUID-VkDescriptorImageInfo-imageView-01976 - if image_view.subresource_range().aspects.depth - && image_view.subresource_range().aspects.stencil + if image_view + .subresource_range() + .aspects + .contains(ImageAspects::DEPTH | ImageAspects::STENCIL) { return Err(DescriptorSetUpdateError::ImageViewDepthAndStencil { binding: write.binding(), diff --git a/vulkano/src/device/physical.rs b/vulkano/src/device/physical.rs index a1f53dfe..3e37e30d 100644 --- a/vulkano/src/device/physical.rs +++ b/vulkano/src/device/physical.rs @@ -14,15 +14,15 @@ use crate::{ device::{properties::Properties, DeviceExtensions, Features, FeaturesFfi, PropertiesFfi}, format::{Format, FormatProperties}, image::{ - ImageFormatInfo, ImageFormatProperties, ImageUsage, SparseImageFormatInfo, + ImageAspects, ImageFormatInfo, ImageFormatProperties, ImageUsage, SparseImageFormatInfo, SparseImageFormatProperties, }, instance::Instance, macros::{vulkan_bitflags, vulkan_enum}, memory::MemoryProperties, swapchain::{ - ColorSpace, FullScreenExclusive, PresentMode, SupportedSurfaceTransforms, Surface, - SurfaceApi, SurfaceCapabilities, SurfaceInfo, + ColorSpace, FullScreenExclusive, PresentMode, Surface, SurfaceApi, SurfaceCapabilities, + SurfaceInfo, SurfaceTransforms, }, sync::{ ExternalFenceInfo, ExternalFenceProperties, ExternalSemaphoreInfo, @@ -442,7 +442,7 @@ impl PhysicalDevice { ) -> Result<(), PhysicalDeviceError> { if !self.instance.enabled_extensions().ext_directfb_surface { return Err(PhysicalDeviceError::RequirementNotMet { - required_for: "`directfb_presentation_support`", + required_for: "`PhysicalDevice::directfb_presentation_support`", requires_one_of: RequiresOneOf { instance_extensions: &["ext_directfb_surface"], ..Default::default() @@ -510,7 +510,7 @@ impl PhysicalDevice { .khr_external_memory_capabilities) { return Err(PhysicalDeviceError::RequirementNotMet { - required_for: "`external_buffer_properties`", + required_for: "`PhysicalDevice::external_buffer_properties`", requires_one_of: RequiresOneOf { api_version: Some(Version::V1_1), instance_extensions: &["khr_external_memory_capabilities"], @@ -623,7 +623,7 @@ impl PhysicalDevice { .khr_external_fence_capabilities) { return Err(PhysicalDeviceError::RequirementNotMet { - required_for: "`external_fence_properties`", + required_for: "`PhysicalDevice::external_fence_properties`", requires_one_of: RequiresOneOf { api_version: Some(Version::V1_1), instance_extensions: &["khr_external_fence_capabilities"], @@ -731,7 +731,7 @@ impl PhysicalDevice { .khr_external_semaphore_capabilities) { return Err(PhysicalDeviceError::RequirementNotMet { - required_for: "`external_semaphore_properties`", + required_for: "`PhysicalDevice::external_semaphore_properties`", requires_one_of: RequiresOneOf { api_version: Some(Version::V1_1), instance_extensions: &["khr_external_semaphore_capabilities"], @@ -941,13 +941,14 @@ impl PhysicalDevice { let format = format.unwrap(); let aspects = format.aspects(); - let has_separate_stencil_usage = - if stencil_usage.is_empty() || !(aspects.depth && aspects.stencil) { - stencil_usage = usage; - false - } else { - stencil_usage == usage - }; + let has_separate_stencil_usage = if stencil_usage.is_empty() + || !aspects.contains(ImageAspects::DEPTH | ImageAspects::STENCIL) + { + stencil_usage = usage; + false + } else { + stencil_usage == usage + }; // VUID-VkPhysicalDeviceImageFormatInfo2-format-parameter format.validate_physical_device(self)?; @@ -969,7 +970,8 @@ impl PhysicalDevice { || self.supported_extensions().ext_separate_stencil_usage) { 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 { api_version: Some(Version::V1_2), device_extensions: &["ext_separate_stencil_usage"], @@ -1040,7 +1042,9 @@ impl PhysicalDevice { 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; } } @@ -1213,7 +1217,7 @@ impl PhysicalDevice { ) -> Result<(), PhysicalDeviceError> { if !self.instance.enabled_extensions().qnx_screen_surface { return Err(PhysicalDeviceError::RequirementNotMet { - required_for: "`qnx_screen_presentation_support`", + required_for: "`PhysicalDevice::qnx_screen_presentation_support`", requires_one_of: RequiresOneOf { instance_extensions: &["qnx_screen_surface"], ..Default::default() @@ -1486,7 +1490,7 @@ impl PhysicalDevice { || self.instance.enabled_extensions().khr_surface) { return Err(PhysicalDeviceError::RequirementNotMet { - required_for: "`surface_capabilities`", + required_for: "`PhysicalDevice::surface_capabilities`", requires_one_of: RequiresOneOf { instance_extensions: &["khr_get_surface_capabilities2", "khr_surface"], ..Default::default() @@ -1655,10 +1659,10 @@ impl PhysicalDevice { .supported_transforms .into(), - current_transform: SupportedSurfaceTransforms::from( + current_transform: SurfaceTransforms::from( capabilities_vk.surface_capabilities.current_transform, ) - .iter() + .into_iter() .next() .unwrap(), // TODO: supported_composite_alpha: capabilities_vk @@ -1668,7 +1672,7 @@ impl PhysicalDevice { supported_usage_flags: { let usage = 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 }, @@ -1711,7 +1715,7 @@ impl PhysicalDevice { || self.instance.enabled_extensions().khr_surface) { return Err(PhysicalDeviceError::RequirementNotMet { - required_for: "`surface_formats`", + required_for: "`PhysicalDevice::surface_formats`", requires_one_of: RequiresOneOf { instance_extensions: &["khr_get_surface_capabilities2", "khr_surface"], ..Default::default() @@ -1928,7 +1932,7 @@ impl PhysicalDevice { fn validate_surface_present_modes(&self, surface: &Surface) -> Result<(), PhysicalDeviceError> { if !self.instance.enabled_extensions().khr_surface { return Err(PhysicalDeviceError::RequirementNotMet { - required_for: "`surface_present_modes`", + required_for: "`PhysicalDevice::surface_present_modes`", requires_one_of: RequiresOneOf { instance_extensions: &["khr_surface"], ..Default::default() @@ -2022,7 +2026,7 @@ impl PhysicalDevice { ) -> Result<(), PhysicalDeviceError> { if !self.instance.enabled_extensions().khr_surface { return Err(PhysicalDeviceError::RequirementNotMet { - required_for: "`surface_support`", + required_for: "`PhysicalDevice::surface_support`", requires_one_of: RequiresOneOf { instance_extensions: &["khr_surface"], ..Default::default() @@ -2084,7 +2088,7 @@ impl PhysicalDevice { fn validate_tool_properties(&self) -> Result<(), PhysicalDeviceError> { if !(self.api_version() >= Version::V1_3 || self.supported_extensions().ext_tooling_info) { return Err(PhysicalDeviceError::RequirementNotMet { - required_for: "`tooling_properties`", + required_for: "`PhysicalDevice::tooling_properties`", requires_one_of: RequiresOneOf { api_version: Some(Version::V1_3), device_extensions: &["ext_tooling_info"], @@ -2195,7 +2199,7 @@ impl PhysicalDevice { ) -> Result<(), PhysicalDeviceError> { if !self.instance.enabled_extensions().khr_wayland_surface { return Err(PhysicalDeviceError::RequirementNotMet { - required_for: "`wayland_presentation_support`", + required_for: "`PhysicalDevice::wayland_presentation_support`", requires_one_of: RequiresOneOf { instance_extensions: &["khr_wayland_surface"], ..Default::default() @@ -2250,7 +2254,7 @@ impl PhysicalDevice { ) -> Result<(), PhysicalDeviceError> { if !self.instance.enabled_extensions().khr_win32_surface { return Err(PhysicalDeviceError::RequirementNotMet { - required_for: "`win32_presentation_support`", + required_for: "`PhysicalDevice::win32_presentation_support`", requires_one_of: RequiresOneOf { instance_extensions: &["khr_win32_surface"], ..Default::default() @@ -2304,7 +2308,7 @@ impl PhysicalDevice { ) -> Result<(), PhysicalDeviceError> { if !self.instance.enabled_extensions().khr_xcb_surface { return Err(PhysicalDeviceError::RequirementNotMet { - required_for: "`xcb_presentation_support`", + required_for: "`PhysicalDevice::xcb_presentation_support`", requires_one_of: RequiresOneOf { instance_extensions: &["khr_xcb_surface"], ..Default::default() @@ -2368,7 +2372,7 @@ impl PhysicalDevice { ) -> Result<(), PhysicalDeviceError> { if !self.instance.enabled_extensions().khr_xlib_surface { return Err(PhysicalDeviceError::RequirementNotMet { - required_for: "`xlib_presentation_support`", + required_for: "`PhysicalDevice::xlib_presentation_support`", requires_one_of: RequiresOneOf { instance_extensions: &["khr_xlib_surface"], ..Default::default() @@ -2420,8 +2424,9 @@ unsafe impl VulkanObject for PhysicalDevice { crate::impl_id_counter!(PhysicalDevice); vulkan_enum! { - /// Type of a physical device. #[non_exhaustive] + + /// Type of a physical device. PhysicalDeviceType = PhysicalDeviceType(i32); /// The device is an integrated GPU. @@ -2482,8 +2487,9 @@ impl Display for ConformanceVersion { } vulkan_enum! { - /// An identifier for the driver of a physical device. #[non_exhaustive] + + /// An identifier for the driver of a physical device. DriverId = DriverId(i32); // TODO: document @@ -2550,78 +2556,81 @@ pub struct ToolProperties { } vulkan_bitflags! { - /// The purpose of an active tool. #[non_exhaustive] + + /// The purpose of an active tool. ToolPurposes = ToolPurposeFlags(u32); /// The tool provides validation of API usage. - validation = VALIDATION, + VALIDATION = VALIDATION, /// The tool provides profiling of API usage. - profiling = PROFILING, + PROFILING = PROFILING, /// 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 /// implementation. - additional_features = ADDITIONAL_FEATURES, + ADDITIONAL_FEATURES = ADDITIONAL_FEATURES, /// 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 /// [`DebugUtilsMessenger`](crate::instance::debug::DebugUtilsMessenger). - debug_reporting = DEBUG_REPORTING_EXT { + DEBUG_REPORTING = DEBUG_REPORTING_EXT { instance_extensions: [ext_debug_utils, ext_debug_report], }, /// The tool consumes debug markers or object debug annotation, queue labels or command buffer /// labels. - debug_markers = DEBUG_MARKERS_EXT { + DEBUG_MARKERS = DEBUG_MARKERS_EXT { device_extensions: [ext_debug_marker], instance_extensions: [ext_debug_utils], }, } vulkan_bitflags! { - /// Specifies which subgroup operations are supported. #[non_exhaustive] + + /// Specifies which subgroup operations are supported. SubgroupFeatures = SubgroupFeatureFlags(u32); // TODO: document - basic = BASIC, + BASIC = BASIC, // TODO: document - vote = VOTE, + VOTE = VOTE, // TODO: document - arithmetic = ARITHMETIC, + ARITHMETIC = ARITHMETIC, // TODO: document - ballot = BALLOT, + BALLOT = BALLOT, // TODO: document - shuffle = SHUFFLE, + SHUFFLE = SHUFFLE, // TODO: document - shuffle_relative = SHUFFLE_RELATIVE, + SHUFFLE_RELATIVE = SHUFFLE_RELATIVE, // TODO: document - clustered = CLUSTERED, + CLUSTERED = CLUSTERED, // TODO: document - quad = QUAD, + QUAD = QUAD, // TODO: document - partitioned = PARTITIONED_NV { + PARTITIONED = PARTITIONED_NV { device_extensions: [nv_shader_subgroup_partitioned], }, } vulkan_enum! { - /// Specifies how the device clips single point primitives. #[non_exhaustive] + + /// Specifies how the device clips single point primitives. PointClippingBehavior = PointClippingBehavior(i32); /// Points are clipped if they lie outside any clip plane, both those bounding the view volume @@ -2633,8 +2642,9 @@ vulkan_enum! { } vulkan_enum! { - /// Specifies whether, and how, shader float controls can be set independently. #[non_exhaustive] + + /// Specifies whether, and how, shader float controls can be set independently. ShaderFloatControlsIndependence = ShaderFloatControlsIndependence(i32); // TODO: document diff --git a/vulkano/src/device/queue.rs b/vulkano/src/device/queue.rs index b2a1b6a7..ed2b28e5 100644 --- a/vulkano/src/device/queue.rs +++ b/vulkano/src/device/queue.rs @@ -1126,7 +1126,7 @@ impl<'a> QueueGuard<'a> { .ext_debug_utils { return Err(QueueError::RequirementNotMet { - required_for: "`begin_debug_utils_label`", + required_for: "`QueueGuard::begin_debug_utils_label`", requires_one_of: RequiresOneOf { instance_extensions: &["ext_debug_utils"], ..Default::default() @@ -1183,7 +1183,7 @@ impl<'a> QueueGuard<'a> { .ext_debug_utils { return Err(QueueError::RequirementNotMet { - required_for: "`end_debug_utils_label`", + required_for: "`QueueGuard::end_debug_utils_label`", requires_one_of: RequiresOneOf { instance_extensions: &["ext_debug_utils"], ..Default::default() @@ -1233,7 +1233,7 @@ impl<'a> QueueGuard<'a> { .ext_debug_utils { return Err(QueueError::RequirementNotMet { - required_for: "`insert_debug_utils_label`", + required_for: "`QueueGuard::insert_debug_utils_label`", requires_one_of: RequiresOneOf { instance_extensions: &["ext_debug_utils"], ..Default::default() @@ -1592,7 +1592,7 @@ impl QueueFamilyProperties { /// Returns whether the queues of this family support a particular pipeline stage. #[inline] 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 for QueueFamilyProperties { } vulkan_bitflags! { - /// Attributes of a queue or queue family. #[non_exhaustive] + + /// Attributes of a queue or queue family. QueueFlags = QueueFlags(u32); /// Queues of this family can execute graphics operations. - graphics = GRAPHICS, + GRAPHICS = GRAPHICS, /// Queues of this family can execute compute operations. - compute = COMPUTE, + COMPUTE = COMPUTE, /// Queues of this family can execute transfer operations. - transfer = TRANSFER, + TRANSFER = TRANSFER, /// 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. - protected = PROTECTED { + PROTECTED = PROTECTED { api_version: V1_1, }, /// 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], }, /// 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], }, } diff --git a/vulkano/src/format.rs b/vulkano/src/format.rs index 352bbd2e..ad4822f8 100644 --- a/vulkano/src/format.rs +++ b/vulkano/src/format.rs @@ -107,8 +107,8 @@ impl Format { note = "Use PhysicalDevice::format_properties instead" )] #[inline] - pub fn properties(&self, physical_device: PhysicalDevice) -> FormatProperties { - physical_device.format_properties(*self).unwrap() + pub fn properties(self, physical_device: PhysicalDevice) -> FormatProperties { + physical_device.format_properties(self).unwrap() } /// 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) /// features are enabled on the device. #[inline] - pub fn shader_storage_image_without_format(&self) -> bool { + pub fn shader_storage_image_without_format(self) -> bool { matches!( - *self, + self, Format::R8G8B8A8_UNORM | Format::R8G8B8A8_SNORM | Format::R8G8B8A8_UINT @@ -254,7 +254,7 @@ pub enum ChromaSampling { impl ChromaSampling { #[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 { ChromaSampling::Mode444 => (), ChromaSampling::Mode422 => { @@ -743,138 +743,139 @@ impl FormatProperties { } vulkan_bitflags! { - /// The features supported by a device for an image or buffer with a particular format. #[non_exhaustive] + + /// The features supported by a device for an image or buffer with a particular format. FormatFeatures = FormatFeatureFlags2(u64); /* Image usage */ /// Can be used with a sampled image descriptor. - sampled_image = SAMPLED_IMAGE, + SAMPLED_IMAGE = SAMPLED_IMAGE, /// 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. - 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 /// image view. - storage_read_without_format = STORAGE_READ_WITHOUT_FORMAT { + STORAGE_READ_WITHOUT_FORMAT = STORAGE_READ_WITHOUT_FORMAT { api_version: V1_3, device_extensions: [khr_format_feature_flags2], }, /// Can be used with a storage image descriptor for writing, without specifying a format on the /// image view. - storage_write_without_format = STORAGE_WRITE_WITHOUT_FORMAT { + STORAGE_WRITE_WITHOUT_FORMAT = STORAGE_WRITE_WITHOUT_FORMAT { api_version: V1_3, device_extensions: [khr_format_feature_flags2], }, /// Can be used with a color attachment in a framebuffer, or with an input attachment /// 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 /// 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 /// 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. - fragment_density_map = FRAGMENT_DENSITY_MAP_EXT { + FRAGMENT_DENSITY_MAP = FRAGMENT_DENSITY_MAP_EXT { device_extensions: [ext_fragment_density_map], }, /// 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], }, /// Can be used with the source image in a transfer (copy) operation. - transfer_src = TRANSFER_SRC { + TRANSFER_SRC = TRANSFER_SRC { api_version: V1_1, device_extensions: [khr_maintenance1], }, /// Can be used with the destination image in a transfer (copy) operation. - transfer_dst = TRANSFER_DST { + TRANSFER_DST = TRANSFER_DST { api_version: V1_1, device_extensions: [khr_maintenance1], }, /// 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. - blit_dst = BLIT_DST, + BLIT_DST = BLIT_DST, /* Sampling */ /// Can be used with samplers or as a blit source, using the /// [`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 /// [`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], }, /// Can be used with samplers using a reduction mode of /// [`Min`](crate::sampler::SamplerReductionMode::Min) or /// [`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, device_extensions: [ext_sampler_filter_minmax], }, /// Can be used with sampler YCbCr conversions using a chroma offset of /// [`Midpoint`](crate::sampler::ycbcr::ChromaLocation::Midpoint). - midpoint_chroma_samples = MIDPOINT_CHROMA_SAMPLES { + MIDPOINT_CHROMA_SAMPLES = MIDPOINT_CHROMA_SAMPLES { api_version: V1_1, device_extensions: [khr_sampler_ycbcr_conversion], }, /// Can be used with sampler YCbCr conversions using a chroma offset of /// [`CositedEven`](crate::sampler::ycbcr::ChromaLocation::CositedEven). - cosited_chroma_samples = COSITED_CHROMA_SAMPLES { + COSITED_CHROMA_SAMPLES = COSITED_CHROMA_SAMPLES { api_version: V1_1, device_extensions: [khr_sampler_ycbcr_conversion], }, /// Can be used with sampler YCbCr conversions using the /// [`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, device_extensions: [khr_sampler_ycbcr_conversion], }, /// Can be used with sampler YCbCr conversions whose chroma filter differs from the filters of /// 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, device_extensions: [khr_sampler_ycbcr_conversion], }, /// When used with a sampler YCbCr conversion, the implementation will always perform /// 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, device_extensions: [khr_sampler_ycbcr_conversion], }, /// 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, device_extensions: [khr_sampler_ycbcr_conversion], }, /// 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, device_extensions: [khr_format_feature_flags2], }, @@ -882,29 +883,31 @@ vulkan_bitflags! { /* Video */ /// 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], }, /// 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], }, /// 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], }, /// 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], }, /* Misc image features */ - /// For multi-planar formats, can be used with images created with the `disjoint` flag. - disjoint = DISJOINT { + /// For multi-planar formats, can be used with images created with the [`DISJOINT`] flag. + /// + /// [`DISJOINT`]: crate::image::ImageCreateFlags::DISJOINT + DISJOINT = DISJOINT { api_version: V1_1, device_extensions: [khr_sampler_ycbcr_conversion], }, @@ -912,20 +915,20 @@ vulkan_bitflags! { /* Buffer usage */ /// 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. - 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. - 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 /// pipeline. - vertex_buffer = VERTEX_BUFFER, + VERTEX_BUFFER = VERTEX_BUFFER, /// 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], }, } diff --git a/vulkano/src/image/aspect.rs b/vulkano/src/image/aspect.rs index f79e74ae..849d8d36 100644 --- a/vulkano/src/image/aspect.rs +++ b/vulkano/src/image/aspect.rs @@ -7,187 +7,90 @@ // notice may not be copied, modified, or distributed except // 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. /// - /// Most images have only the `Color` aspect, but some may have several. - #[non_exhaustive] - ImageAspect = ImageAspectFlags(u32); + /// Most images have only the [`Color`] aspect, but some may have others. + /// + /// [`Color`]: ImageAspect::Color + ImageAspect, - // TODO: document - Color = COLOR, + = ImageAspectFlags(u32); - // TODO: document - Depth = DEPTH, + /// The single aspect of images with a color [format], or the combined aspect of all planes of + /// images with a multi-planar format. + /// + /// [format]: crate::format::Format + COLOR, Color = COLOR, - // TODO: document - Stencil = STENCIL, + /// The single aspect of images with a depth [format], or one of the two aspects of images + /// with a combined depth/stencil format. + /// + /// [format]: crate::format::Format + DEPTH, Depth = DEPTH, - // TODO: document - Metadata = METADATA, + /// The single aspect of images with a stencil [format], or one of the two aspects of images + /// with a combined depth/stencil format. + /// + /// [format]: crate::format::Format + STENCIL, Stencil = STENCIL, - // TODO: document - Plane0 = PLANE_0 { + /// An aspect used with sparse memory on some implementations, to hold implementation-defined + /// 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, device_extensions: [khr_sampler_ycbcr_conversion], }, - // TODO: document - Plane1 = PLANE_1 { + /// The second plane of an image with a multi-planar [format], holding the blue color component + /// 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, device_extensions: [khr_sampler_ycbcr_conversion], }, - // TODO: document - Plane2 = PLANE_2 { + /// The third plane of an image with a multi-planar [format], holding the red color component. + PLANE_2, Plane2 = PLANE_2 { api_version: V1_1, device_extensions: [khr_sampler_ycbcr_conversion], }, - // TODO: document - MemoryPlane0 = MEMORY_PLANE_0_EXT { + /// The first memory plane of images created through the [`ext_image_drm_format_modifier`] + /// 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], }, - // TODO: document - MemoryPlane1 = MEMORY_PLANE_1_EXT { + /// The second memory plane of images created through the [`ext_image_drm_format_modifier`] + /// 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], }, - // TODO: document - MemoryPlane2 = MEMORY_PLANE_2_EXT { + /// The third memory plane of images created through the [`ext_image_drm_format_modifier`] + /// 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], }, } - -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 { - 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 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 for ImageAspects { - fn from_iter>(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 - } -} diff --git a/vulkano/src/image/attachment.rs b/vulkano/src/image/attachment.rs index 5492a6c7..44370851 100644 --- a/vulkano/src/image/attachment.rs +++ b/vulkano/src/image/attachment.rs @@ -10,8 +10,8 @@ use super::{ sys::{Image, ImageMemory, RawImage}, traits::ImageContent, - ImageAccess, ImageDescriptorLayouts, ImageError, ImageInner, ImageLayout, ImageUsage, - SampleCount, + ImageAccess, ImageAspects, ImageDescriptorLayouts, ImageError, ImageInner, ImageLayout, + ImageUsage, SampleCount, }; use crate::{ device::{Device, DeviceOwned}, @@ -108,10 +108,7 @@ impl AttachmentImage { dimensions: [u32; 2], format: Format, ) -> Result, ImageError> { - let base_usage = ImageUsage { - input_attachment: true, - ..ImageUsage::empty() - }; + let base_usage = ImageUsage::INPUT_ATTACHMENT; AttachmentImage::new_impl( allocator, @@ -154,10 +151,7 @@ impl AttachmentImage { samples: SampleCount, format: Format, ) -> Result, ImageError> { - let base_usage = ImageUsage { - input_attachment: true, - ..ImageUsage::empty() - }; + let base_usage = ImageUsage::INPUT_ATTACHMENT; AttachmentImage::new_impl(allocator, dimensions, 1, format, base_usage, samples) } @@ -224,10 +218,7 @@ impl AttachmentImage { dimensions: [u32; 2], format: Format, ) -> Result, ImageError> { - let base_usage = ImageUsage { - sampled: true, - ..ImageUsage::empty() - }; + let base_usage = ImageUsage::SAMPLED; AttachmentImage::new_impl( allocator, @@ -248,11 +239,7 @@ impl AttachmentImage { dimensions: [u32; 2], format: Format, ) -> Result, ImageError> { - let base_usage = ImageUsage { - sampled: true, - input_attachment: true, - ..ImageUsage::empty() - }; + let base_usage = ImageUsage::SAMPLED | ImageUsage::INPUT_ATTACHMENT; AttachmentImage::new_impl( allocator, @@ -277,10 +264,7 @@ impl AttachmentImage { samples: SampleCount, format: Format, ) -> Result, ImageError> { - let base_usage = ImageUsage { - sampled: true, - ..ImageUsage::empty() - }; + let base_usage = ImageUsage::SAMPLED; AttachmentImage::new_impl(allocator, dimensions, 1, format, base_usage, samples) } @@ -296,11 +280,7 @@ impl AttachmentImage { samples: SampleCount, format: Format, ) -> Result, ImageError> { - let base_usage = ImageUsage { - sampled: true, - input_attachment: true, - ..ImageUsage::empty() - }; + let base_usage = ImageUsage::SAMPLED | ImageUsage::INPUT_ATTACHMENT; AttachmentImage::new_impl(allocator, dimensions, 1, format, base_usage, samples) } @@ -317,10 +297,7 @@ impl AttachmentImage { dimensions: [u32; 2], format: Format, ) -> Result, ImageError> { - let base_usage = ImageUsage { - transient_attachment: true, - ..ImageUsage::empty() - }; + let base_usage = ImageUsage::TRANSIENT_ATTACHMENT; AttachmentImage::new_impl( allocator, @@ -341,11 +318,7 @@ impl AttachmentImage { dimensions: [u32; 2], format: Format, ) -> Result, ImageError> { - let base_usage = ImageUsage { - transient_attachment: true, - input_attachment: true, - ..ImageUsage::empty() - }; + let base_usage = ImageUsage::TRANSIENT_ATTACHMENT | ImageUsage::INPUT_ATTACHMENT; AttachmentImage::new_impl( allocator, @@ -370,10 +343,7 @@ impl AttachmentImage { samples: SampleCount, format: Format, ) -> Result, ImageError> { - let base_usage = ImageUsage { - transient_attachment: true, - ..ImageUsage::empty() - }; + let base_usage = ImageUsage::TRANSIENT_ATTACHMENT; AttachmentImage::new_impl(allocator, dimensions, 1, format, base_usage, samples) } @@ -389,11 +359,7 @@ impl AttachmentImage { samples: SampleCount, format: Format, ) -> Result, ImageError> { - let base_usage = ImageUsage { - transient_attachment: true, - input_attachment: true, - ..ImageUsage::empty() - }; + let base_usage = ImageUsage::TRANSIENT_ATTACHMENT | ImageUsage::INPUT_ATTACHMENT; AttachmentImage::new_impl(allocator, dimensions, 1, format, base_usage, samples) } @@ -404,7 +370,7 @@ impl AttachmentImage { dimensions: [u32; 2], array_layers: u32, format: Format, - base_usage: ImageUsage, + mut usage: ImageUsage, samples: SampleCount, ) -> Result, ImageError> { let physical_device = allocator.device().physical_device(); @@ -421,7 +387,15 @@ impl AttachmentImage { } 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() { panic!() // TODO: message? @@ -437,11 +411,7 @@ impl AttachmentImage { }, format: Some(format), samples, - usage: ImageUsage { - color_attachment: !is_depth, - depth_stencil_attachment: is_depth, - ..base_usage - }, + usage, ..Default::default() }, )?; @@ -467,7 +437,7 @@ impl AttachmentImage { Ok(Arc::new(AttachmentImage { inner, - attachment_layout: if is_depth { + attachment_layout: if is_depth_stencil { ImageLayout::DepthStencilAttachmentOptimal } else { ImageLayout::ColorAttachmentOptimal @@ -484,7 +454,7 @@ impl AttachmentImage { dimensions: [u32; 2], array_layers: u32, format: Format, - base_usage: ImageUsage, + mut usage: ImageUsage, samples: SampleCount, ) -> Result, ImageError> { let physical_device = allocator.device().physical_device(); @@ -501,21 +471,21 @@ impl AttachmentImage { } let aspects = format.aspects(); - let is_depth = aspects.depth || aspects.stencil; - let usage = ImageUsage { - color_attachment: !is_depth, - depth_stencil_attachment: is_depth, - ..base_usage - }; + 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; + } let external_memory_properties = allocator .device() .physical_device() .image_format_properties(ImageFormatInfo { - flags: ImageCreateFlags { - mutable_format: true, - ..ImageCreateFlags::empty() - }, + flags: ImageCreateFlags::MUTABLE_FORMAT, format: Some(format), usage, external_memory_handle_type: Some(ExternalMemoryHandleType::OpaqueFd), @@ -530,17 +500,11 @@ impl AttachmentImage { // VUID-VkMemoryAllocateInfo-pNext-00639 // Guaranteed because we always create a dedicated allocation - let external_memory_handle_types = ExternalMemoryHandleTypes { - opaque_fd: true, - ..ExternalMemoryHandleTypes::empty() - }; + let external_memory_handle_types = ExternalMemoryHandleTypes::OPAQUE_FD; let raw_image = RawImage::new( allocator.device().clone(), ImageCreateInfo { - flags: ImageCreateFlags { - mutable_format: true, - ..ImageCreateFlags::empty() - }, + flags: ImageCreateFlags::MUTABLE_FORMAT, dimensions: ImageDimensions::Dim2d { width: dimensions[0], height: dimensions[1], @@ -577,7 +541,7 @@ impl AttachmentImage { Ok(Arc::new(AttachmentImage { inner, - attachment_layout: if is_depth { + attachment_layout: if is_depth_stencil { ImageLayout::DepthStencilAttachmentOptimal } else { ImageLayout::ColorAttachmentOptimal diff --git a/vulkano/src/image/immutable.rs b/vulkano/src/image/immutable.rs index b71128db..72aa93eb 100644 --- a/vulkano/src/image/immutable.rs +++ b/vulkano/src/image/immutable.rs @@ -115,7 +115,7 @@ impl ImmutableImage { ) -> Result<(Arc, Arc), ImmutableImageCreationError> { 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( allocator.device().clone(), @@ -188,15 +188,8 @@ impl ImmutableImage { I::IntoIter: ExactSizeIterator, A: CommandBufferAllocator, { - let source = CpuAccessibleBuffer::from_iter( - allocator, - BufferUsage { - transfer_src: true, - ..BufferUsage::empty() - }, - false, - iter, - )?; + let source = + CpuAccessibleBuffer::from_iter(allocator, BufferUsage::TRANSFER_SRC, false, iter)?; ImmutableImage::from_buffer( allocator, @@ -246,12 +239,13 @@ impl ImmutableImage { } let need_to_generate_mipmaps = has_mipmaps(mip_levels); - let usage = ImageUsage { - transfer_dst: true, - transfer_src: need_to_generate_mipmaps, - sampled: true, - ..ImageUsage::empty() - }; + let usage = ImageUsage::TRANSFER_DST + | ImageUsage::SAMPLED + | if need_to_generate_mipmaps { + ImageUsage::TRANSFER_SRC + } else { + ImageUsage::empty() + }; let flags = ImageCreateFlags::empty(); let layout = ImageLayout::ShaderReadOnlyOptimal; diff --git a/vulkano/src/image/layout.rs b/vulkano/src/image/layout.rs index f64c7940..01aea5fe 100644 --- a/vulkano/src/image/layout.rs +++ b/vulkano/src/image/layout.rs @@ -10,6 +10,8 @@ use crate::{descriptor_set::layout::DescriptorType, macros::vulkan_enum}; vulkan_enum! { + #[non_exhaustive] + /// 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 @@ -34,7 +36,6 @@ vulkan_enum! { /// 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 /// layout transitions where needed. - #[non_exhaustive] ImageLayout = ImageLayout(i32); /// The layout of the data is unknown, and the image is treated as containing no valid data. diff --git a/vulkano/src/image/mod.rs b/vulkano/src/image/mod.rs index 7865ab78..f4649374 100644 --- a/vulkano/src/image/mod.rs +++ b/vulkano/src/image/mod.rs @@ -60,7 +60,7 @@ pub use self::{ }; use crate::{ format::Format, - macros::{vulkan_bitflags, vulkan_enum}, + macros::{vulkan_bitflags, vulkan_bitflags_enum, vulkan_enum}, memory::{ExternalMemoryHandleType, ExternalMemoryProperties}, DeviceSize, }; @@ -78,8 +78,9 @@ mod usage; pub mod view; vulkan_bitflags! { - /// Flags that can be set when creating a new image. #[non_exhaustive] + + /// Flags that can be set when creating a new image. ImageCreateFlags = ImageCreateFlags(u32); /* @@ -90,7 +91,7 @@ vulkan_bitflags! { /// /// [`bind_memory`]: sys::RawImage::bind_memory /// [`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. /// @@ -110,7 +111,7 @@ vulkan_bitflags! { /// [`sparse_residency4_samples`]: crate::device::Features::sparse_residency4_samples /// [`sparse_residency8_samples`]: crate::device::Features::sparse_residency8_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. /// @@ -119,7 +120,7 @@ vulkan_bitflags! { /// The [`sparse_residency_aliased`] feature must be enabled on the device. /// /// [`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 @@ -127,24 +128,24 @@ vulkan_bitflags! { /// /// For multi-planar formats, whether an image view wrapping the image can be created from a /// 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 /// [`ImageViewType::CubeArray`] can be created from the image. /// /// [`ImageViewType::Cube`]: crate::image::view::ImageViewType::Cube /// [`ImageViewType::CubeArray`]: crate::image::view::ImageViewType::CubeArray - cube_compatible = CUBE_COMPATIBLE, + CUBE_COMPATIBLE = CUBE_COMPATIBLE, /* // TODO: document - alias = ALIAS { + ALIAS = ALIAS { api_version: V1_1, device_extensions: [khr_bind_memory2], }, // TODO: document - split_instance_bind_regions = SPLIT_INSTANCE_BIND_REGIONS { + SPLIT_INSTANCE_BIND_REGIONS = SPLIT_INSTANCE_BIND_REGIONS { api_version: V1_1, device_extensions: [khr_device_group], }, @@ -160,7 +161,7 @@ vulkan_bitflags! { /// [`ImageViewType::Dim2dArray`]: crate::image::view::ImageViewType::Dim2dArray /// [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 - array_2d_compatible = TYPE_2D_ARRAY_COMPATIBLE { + ARRAY_2D_COMPATIBLE = TYPE_2D_ARRAY_COMPATIBLE { api_version: V1_1, device_extensions: [khr_maintenance1], }, @@ -170,89 +171,115 @@ vulkan_bitflags! { /// compressed texel block in the image. /// /// Requires `mutable_format`. - block_texel_view_compatible = BLOCK_TEXEL_VIEW_COMPATIBLE { + BLOCK_TEXEL_VIEW_COMPATIBLE = BLOCK_TEXEL_VIEW_COMPATIBLE { api_version: V1_1, device_extensions: [khr_maintenance2], }, /* // TODO: document - extended_usage = EXTENDED_USAGE { + EXTENDED_USAGE = EXTENDED_USAGE { api_version: V1_1, device_extensions: [khr_maintenance2], }, // TODO: document - protected = PROTECTED { + PROTECTED = PROTECTED { api_version: V1_1, }, */ /// 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. - disjoint = DISJOINT { + DISJOINT = DISJOINT { api_version: V1_1, device_extensions: [khr_sampler_ycbcr_conversion], }, /* // TODO: document - corner_sampled = CORNER_SAMPLED_NV { + CORNER_SAMPLED = CORNER_SAMPLED_NV { device_extensions: [nv_corner_sampled_image], }, // 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], }, // TODO: document - subsampled = SUBSAMPLED_EXT { + SUBSAMPLED = SUBSAMPLED_EXT { device_extensions: [ext_fragment_density_map], }, // 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], }, // 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], }, // 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], }, */ } -vulkan_enum! { - // TODO: document +vulkan_bitflags_enum! { #[non_exhaustive] - SampleCount = SampleCountFlags(u32); - // TODO: document - Sample1 = TYPE_1, + /// A set of [`SampleCount`] values. + 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 - Sample2 = TYPE_2, + /// The number of samples per texel of an image. + SampleCount, - // TODO: document - Sample4 = TYPE_4, + = SampleCountFlags(u32); - // TODO: document - Sample8 = TYPE_8, + /// 1 sample per texel. + SAMPLE_1, Sample1 = TYPE_1, - // TODO: document - Sample16 = TYPE_16, + /// 2 samples per texel. + SAMPLE_2, Sample2 = TYPE_2, - // TODO: document - Sample32 = TYPE_32, + /// 4 samples per texel. + SAMPLE_4, Sample4 = TYPE_4, - // TODO: document - Sample64 = TYPE_64, + /// 8 samples per texel. + 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 for SampleCount { @@ -273,63 +300,6 @@ impl TryFrom 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. /// /// Note that at least one mipmap must be allocated, to store the main level of the image. @@ -358,8 +328,9 @@ impl From for MipmapsCount { } vulkan_enum! { - // TODO: document #[non_exhaustive] + + // TODO: document ImageType = ImageType(i32); // TODO: document @@ -373,8 +344,9 @@ vulkan_enum! { } vulkan_enum! { - // TODO: document #[non_exhaustive] + + // TODO: document ImageTiling = ImageTiling(i32); // TODO: document @@ -625,11 +597,8 @@ impl ImageSubresourceLayers { aspects: { let aspects = format.aspects(); - if aspects.plane0 { - ImageAspects { - plane0: true, - ..ImageAspects::empty() - } + if aspects.intersects(ImageAspects::PLANE_0) { + ImageAspects::PLANE_0 } else { aspects } @@ -678,12 +647,8 @@ impl ImageSubresourceRange { #[inline] pub fn from_parameters(format: Format, mip_levels: u32, array_layers: u32) -> Self { Self { - aspects: ImageAspects { - plane0: false, - plane1: false, - plane2: false, - ..format.aspects() - }, + aspects: format.aspects() + - (ImageAspects::PLANE_0 | ImageAspects::PLANE_1 | ImageAspects::PLANE_2), mip_levels: 0..mip_levels, array_layers: 0..array_layers, } @@ -946,19 +911,21 @@ pub struct SparseImageFormatProperties { } vulkan_bitflags! { + #[non_exhaustive] + /// Flags specifying information about a sparse resource. SparseImageFormatFlags = SparseImageFormatFlags(u32); /// The image uses a single mip tail region for all array layers, instead of one mip tail region /// 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 /// 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. - nonstandard_block_size = NONSTANDARD_BLOCK_SIZE, + NONSTANDARD_BLOCK_SIZE = NONSTANDARD_BLOCK_SIZE, } /// Requirements for binding memory to a sparse image. diff --git a/vulkano/src/image/storage.rs b/vulkano/src/image/storage.rs index 7ae99541..3d4aea88 100644 --- a/vulkano/src/image/storage.rs +++ b/vulkano/src/image/storage.rs @@ -10,8 +10,8 @@ use super::{ sys::{Image, ImageMemory, RawImage}, traits::ImageContent, - ImageAccess, ImageCreateFlags, ImageDescriptorLayouts, ImageDimensions, ImageError, ImageInner, - ImageLayout, ImageUsage, + ImageAccess, ImageAspects, ImageCreateFlags, ImageDescriptorLayouts, ImageDimensions, + ImageError, ImageInner, ImageLayout, ImageUsage, }; use crate::{ device::{Device, DeviceOwned, Queue}, @@ -51,22 +51,22 @@ impl StorageImage { queue_family_indices: impl IntoIterator, ) -> Result, ImageError> { 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() { panic!() // TODO: message? } - let usage = ImageUsage { - transfer_src: true, - transfer_dst: true, - sampled: true, - storage: true, - color_attachment: !is_depth, - depth_stencil_attachment: is_depth, - input_attachment: true, - ..ImageUsage::empty() - }; + let usage = ImageUsage::TRANSFER_SRC + | ImageUsage::TRANSFER_DST + | ImageUsage::SAMPLED + | ImageUsage::STORAGE + | ImageUsage::INPUT_ATTACHMENT + | if is_depth_stencil { + ImageUsage::DEPTH_STENCIL_ATTACHMENT + } else { + ImageUsage::COLOR_ATTACHMENT + }; let flags = ImageCreateFlags::empty(); StorageImage::with_usage( @@ -89,7 +89,7 @@ impl StorageImage { queue_family_indices: impl IntoIterator, ) -> Result, ImageError> { 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( allocator.device().clone(), @@ -141,7 +141,7 @@ impl StorageImage { queue_family_indices: impl IntoIterator, ) -> Result, ImageError> { 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 .device() @@ -163,10 +163,7 @@ impl StorageImage { // VUID-VkMemoryAllocateInfo-pNext-00639 // Guaranteed because we always create a dedicated allocation - let external_memory_handle_types = ExternalMemoryHandleTypes { - opaque_fd: true, - ..ExternalMemoryHandleTypes::empty() - }; + let external_memory_handle_types = ExternalMemoryHandleTypes::OPAQUE_FD; let raw_image = RawImage::new( allocator.device().clone(), ImageCreateInfo { @@ -360,12 +357,8 @@ mod tests { fn create_general_purpose_image_view() { let (device, queue) = gfx_dev_and_queue!(); let memory_allocator = StandardMemoryAllocator::new_default(device); - let usage = ImageUsage { - transfer_src: true, - transfer_dst: true, - color_attachment: true, - ..ImageUsage::empty() - }; + let usage = + ImageUsage::TRANSFER_SRC | ImageUsage::TRANSFER_DST | ImageUsage::COLOR_ATTACHMENT; let img_view = StorageImage::general_purpose_image_view( &memory_allocator, queue, @@ -374,7 +367,7 @@ mod tests { usage, ) .unwrap(); - assert_eq!(img_view.image().usage(), &usage); + assert_eq!(img_view.image().usage(), usage); } #[test] @@ -382,10 +375,7 @@ mod tests { let (device, queue) = gfx_dev_and_queue!(); let memory_allocator = StandardMemoryAllocator::new_default(device); // Not valid for image view... - let usage = ImageUsage { - transfer_src: true, - ..ImageUsage::empty() - }; + let usage = ImageUsage::TRANSFER_SRC; let img_result = StorageImage::general_purpose_image_view( &memory_allocator, queue, diff --git a/vulkano/src/image/sys.rs b/vulkano/src/image/sys.rs index 908a9a83..64a9128a 100644 --- a/vulkano/src/image/sys.rs +++ b/vulkano/src/image/sys.rs @@ -29,7 +29,8 @@ use crate::{ }, memory::{ allocator::{AllocationCreationError, MemoryAlloc}, - DedicatedTo, ExternalMemoryHandleType, ExternalMemoryHandleTypes, MemoryRequirements, + DedicatedTo, ExternalMemoryHandleType, ExternalMemoryHandleTypes, MemoryPropertyFlags, + MemoryRequirements, }, range_map::RangeMap, 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 aspects = format.aspects(); - let has_separate_stencil_usage = - if stencil_usage.is_empty() || !(aspects.depth && aspects.stencil) { - stencil_usage = usage; - false - } else { - stencil_usage == usage - }; + let has_separate_stencil_usage = if stencil_usage.is_empty() + || !aspects.contains(ImageAspects::DEPTH | ImageAspects::STENCIL) + { + stencil_usage = usage; + false + } else { + stencil_usage == usage + }; // VUID-VkImageCreateInfo-flags-parameter flags.validate_device(device)?; @@ -171,7 +173,8 @@ impl RawImage { || device.enabled_extensions().ext_separate_stencil_usage) { 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 { api_version: Some(Version::V1_2), device_extensions: &["ext_separate_stencil_usage"], @@ -197,7 +200,10 @@ impl RawImage { )); // 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 let format_features = { @@ -266,7 +272,7 @@ impl RawImage { return Err(ImageError::MultisampleNot2d); } - if flags.cube_compatible { + if flags.intersects(ImageCreateFlags::CUBE_COMPATIBLE) { return Err(ImageError::MultisampleCubeCompatible); } @@ -284,10 +290,9 @@ impl RawImage { && array_layers != 1 { return Err(ImageError::RequirementNotMet { - required_for: - "this device is a portability subset device, `create_info.samples` is not \ - `SampleCount::Sample1` and `create_info.dimensions.array_layers()` is \ - greater than `1`", + required_for: "this device is a portability subset device, \ + `create_info.samples` is not `SampleCount::Sample1` and \ + `create_info.dimensions.array_layers()` is greater than `1`", requires_one_of: RequiresOneOf { features: &["multisample_array_image"], ..Default::default() @@ -316,7 +321,8 @@ impl RawImage { // VUID-VkImageCreateInfo-format-06413 if array_layers > 1 && !device.enabled_features().ycbcr_image_arrays { 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 { features: &["ycbcr_image_arrays"], ..Default::default() @@ -346,35 +352,44 @@ impl RawImage { 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" }); } - 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 { 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 { usage: "depth_stencil_attachment", }); } - if combined_usage.input_attachment - && !(format_features.color_attachment || format_features.depth_stencil_attachment) + if combined_usage.intersects(ImageUsage::INPUT_ATTACHMENT) + && !format_features.intersects( + FormatFeatures::COLOR_ATTACHMENT | FormatFeatures::DEPTH_STENCIL_ATTACHMENT, + ) { return Err(ImageError::FormatUsageNotSupported { usage: "input_attachment", }); } - if combined_usage.color_attachment - || combined_usage.depth_stencil_attachment - || combined_usage.input_attachment - || combined_usage.transient_attachment - { + if combined_usage.intersects( + ImageUsage::COLOR_ATTACHMENT + | ImageUsage::DEPTH_STENCIL_ATTACHMENT + | ImageUsage::INPUT_ATTACHMENT + | ImageUsage::TRANSIENT_ATTACHMENT, + ) { // VUID-VkImageCreateInfo-usage-00964 // VUID-VkImageCreateInfo-usage-00965 // VUID-VkImageCreateInfo-Format-02536 @@ -392,8 +407,8 @@ impl RawImage { } } - if combined_usage.storage { - if !format_features.storage_image { + if combined_usage.intersects(ImageUsage::STORAGE) { + if !format_features.intersects(FormatFeatures::STORAGE_IMAGE) { return Err(ImageError::FormatUsageNotSupported { usage: "storage" }); } @@ -403,7 +418,9 @@ impl RawImage { && samples != SampleCount::Sample1 { 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 { features: &["shader_storage_image_multisample"], ..Default::default() @@ -414,40 +431,46 @@ impl RawImage { // These flags only exist in later versions, ignore them otherwise 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 { 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 { usage: "transfer_dst", }); } } - if usage.transient_attachment { + if usage.intersects(ImageUsage::TRANSIENT_ATTACHMENT) { // VUID-VkImageCreateInfo-usage-00966 - assert!( - usage.color_attachment || usage.depth_stencil_attachment || usage.input_attachment - ); + assert!(usage.intersects( + ImageUsage::COLOR_ATTACHMENT + | ImageUsage::DEPTH_STENCIL_ATTACHMENT + | ImageUsage::INPUT_ATTACHMENT + )); // VUID-VkImageCreateInfo-usage-00963 - assert!(ImageUsage { - transient_attachment: false, - color_attachment: false, - depth_stencil_attachment: false, - input_attachment: false, - ..usage - } - .is_empty()) + assert!((usage + - (ImageUsage::TRANSIENT_ATTACHMENT + | ImageUsage::COLOR_ATTACHMENT + | ImageUsage::DEPTH_STENCIL_ATTACHMENT + | ImageUsage::INPUT_ATTACHMENT)) + .is_empty()) } if has_separate_stencil_usage { // VUID-VkImageCreateInfo-format-02795 // 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 { usage, stencil_usage, @@ -456,28 +479,28 @@ impl RawImage { // VUID-VkImageCreateInfo-format-02797 // 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 { usage, stencil_usage, }); } - if stencil_usage.transient_attachment { + if stencil_usage.intersects(ImageUsage::TRANSIENT_ATTACHMENT) { // VUID-VkImageStencilUsageCreateInfo-stencilUsage-02539 - assert!(ImageUsage { - transient_attachment: false, - depth_stencil_attachment: false, - input_attachment: false, - ..stencil_usage - } - .is_empty()) + assert!((stencil_usage + - (ImageUsage::TRANSIENT_ATTACHMENT + | ImageUsage::DEPTH_STENCIL_ATTACHMENT + | ImageUsage::INPUT_ATTACHMENT)) + .is_empty()) } } /* Check flags requirements */ - if flags.cube_compatible { + if flags.intersects(ImageCreateFlags::CUBE_COMPATIBLE) { // VUID-VkImageCreateInfo-flags-00949 if image_type != ImageType::Dim2d { 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 if image_type != ImageType::Dim3d { return Err(ImageError::Array2dCompatibleNot3d); @@ -505,9 +528,8 @@ impl RawImage { && !device.enabled_features().image_view2_d_on3_d_image { return Err(ImageError::RequirementNotMet { - required_for: - "this device is a portability subset device, and the `array_2d_compatible` - flag is enabled", + required_for: "this device is a portability subset device, and \ + `create_info.flags` contains `ImageCreateFlags::ARRAY_2D_COMPATIBLE`", requires_one_of: RequiresOneOf { features: &["image_view2_d_on3_d_image"], ..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 if format.compression().is_none() { return Err(ImageError::BlockTexelViewCompatibleNotCompressed); } } - if flags.disjoint { + if flags.intersects(ImageCreateFlags::DISJOINT) { // VUID-VkImageCreateInfo-format-01577 if format.planes().len() < 2 { return Err(ImageError::DisjointFormatNotSupported); } // VUID-VkImageCreateInfo-imageCreateFormatFeatures-02260 - if !format_features.disjoint { + if !format_features.intersects(FormatFeatures::DISJOINT) { return Err(ImageError::DisjointFormatNotSupported); } } @@ -598,7 +620,7 @@ impl RawImage { let limit = device.physical_device().properties().max_image_dimension1_d; extent[0] > limit } - ImageType::Dim2d if flags.cube_compatible => { + ImageType::Dim2d if flags.intersects(ImageCreateFlags::CUBE_COMPATIBLE) => { let limit = device .physical_device() .properties() @@ -641,41 +663,41 @@ impl RawImage { return false; } - if combined_usage.color_attachment + if combined_usage.intersects(ImageUsage::COLOR_ATTACHMENT) && !device_properties .framebuffer_color_sample_counts - .contains_count(samples) + .contains_enum(samples) { // TODO: how to handle framebuffer_integer_color_sample_counts limit, which only // exists >= Vulkan 1.2 return true; } - if combined_usage.depth_stencil_attachment { - if aspects.depth + if combined_usage.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT) { + if aspects.intersects(ImageAspects::DEPTH) && !device_properties .framebuffer_depth_sample_counts - .contains_count(samples) + .contains_enum(samples) { return true; } - if aspects.stencil + if aspects.intersects(ImageAspects::STENCIL) && !device_properties .framebuffer_stencil_sample_counts - .contains_count(samples) + .contains_enum(samples) { return true; } } - if combined_usage.sampled { + if combined_usage.intersects(ImageUsage::SAMPLED) { if let Some(numeric_type) = format.type_color() { match numeric_type { NumericType::UINT | NumericType::SINT => { if !device_properties .sampled_image_integer_sample_counts - .contains_count(samples) + .contains_enum(samples) { return true; } @@ -689,35 +711,35 @@ impl RawImage { | NumericType::SRGB => { if !device_properties .sampled_image_color_sample_counts - .contains_count(samples) + .contains_enum(samples) { return true; } } } } else { - if aspects.depth + if aspects.intersects(ImageAspects::DEPTH) && !device_properties .sampled_image_depth_sample_counts - .contains_count(samples) + .contains_enum(samples) { return true; } - if aspects.stencil + if aspects.intersects(ImageAspects::STENCIL) && device_properties .sampled_image_stencil_sample_counts - .contains_count(samples) + .contains_enum(samples) { return true; } } } - if combined_usage.storage + if combined_usage.intersects(ImageUsage::STORAGE) && !device_properties .storage_image_sample_counts - .contains_count(samples) + .contains_enum(samples) { return true; } @@ -733,11 +755,7 @@ impl RawImage { && array_layers == 1 // VUID-VkImageCreateInfo-samples-02257 already states that multisampling+linear // is invalid so no need to check for that here. - && ImageUsage { - transfer_src: false, - transfer_dst: false, - ..usage - }.is_empty()) + && (usage - (ImageUsage::TRANSFER_SRC | ImageUsage::TRANSFER_DST)).is_empty()) } else { false } @@ -756,7 +774,7 @@ impl RawImage { if !external_memory_handle_types.is_empty() { // If external memory handles are used, the properties need to be queried // individually for each handle type. - external_memory_handle_types.iter().map(Some).collect() + external_memory_handle_types.into_iter().map(Some).collect() } else { smallvec![None] }; @@ -819,7 +837,7 @@ impl RawImage { } // VUID-VkImageCreateInfo-samples-02258 - if !sample_counts.contains_count(samples) { + if !sample_counts.contains_enum(samples) { return Err(ImageError::SampleCountNotSupported { samples, supported: sample_counts, @@ -856,13 +874,14 @@ impl RawImage { let aspects = format.map_or_else(Default::default, |format| format.aspects()); - let has_separate_stencil_usage = - if stencil_usage.is_empty() || !(aspects.depth && aspects.stencil) { - stencil_usage = usage; - false - } else { - stencil_usage == usage - }; + let has_separate_stencil_usage = if stencil_usage.is_empty() + || !aspects.contains(ImageAspects::DEPTH | ImageAspects::STENCIL) + { + stencil_usage = usage; + false + } else { + stencil_usage == usage + }; let (image_type, extent, array_layers) = match dimensions { ImageDimensions::Dim1d { @@ -984,7 +1003,9 @@ impl RawImage { 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; } @@ -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()) .map(|plane| Self::get_memory_requirements(&device, handle, Some(plane))) .collect() @@ -1342,7 +1363,7 @@ impl RawImage { } 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() { return Err(ImageError::AllocationsWrongNumberOfElements { provided: allocations.len(), @@ -1398,7 +1419,10 @@ impl RawImage { } // VUID-VkBindImageMemoryInfo-None-01901 - if memory_type.property_flags.protected { + if memory_type + .property_flags + .intersects(MemoryPropertyFlags::PROTECTED) + { return Err(ImageError::MemoryProtectedMismatch { allocations_index, image_protected: false, @@ -1410,7 +1434,7 @@ impl RawImage { if !memory.export_handle_types().is_empty() && !memory .export_handle_types() - .intersects(&self.external_memory_handle_types) + .intersects(self.external_memory_handle_types) { return Err(ImageError::MemoryExternalHandleTypesDisjoint { allocations_index, @@ -1422,7 +1446,7 @@ impl RawImage { if let Some(handle_type) = memory.imported_handle_type() { // VUID-VkBindImageMemoryInfo-memory-02989 if !ExternalMemoryHandleTypes::from(handle_type) - .intersects(&self.external_memory_handle_types) + .intersects(self.external_memory_handle_types) { return Err(ImageError::MemoryImportedHandleTypeNotEnabled { allocations_index, @@ -1493,7 +1517,7 @@ impl RawImage { let mut 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()); for (plane, allocation) in allocations.iter().enumerate() { @@ -1602,8 +1626,8 @@ impl RawImage { /// Returns the features supported by the image's format. #[inline] - pub fn format_features(&self) -> &FormatFeatures { - &self.format_features + pub fn format_features(&self) -> FormatFeatures { + self.format_features } /// Returns the number of mipmap levels in the image. @@ -1632,14 +1656,14 @@ impl RawImage { /// Returns the usage the image was created with. #[inline] - pub fn usage(&self) -> &ImageUsage { - &self.usage + pub fn usage(&self) -> ImageUsage { + self.usage } /// Returns the stencil usage the image was created with. #[inline] - pub fn stencil_usage(&self) -> &ImageUsage { - &self.stencil_usage + pub fn stencil_usage(&self) -> ImageUsage { + self.stencil_usage } /// Returns the sharing the image was created with. @@ -1662,11 +1686,8 @@ impl RawImage { aspects: { let aspects = self.format.unwrap().aspects(); - if aspects.plane0 { - ImageAspects { - plane0: true, - ..ImageAspects::empty() - } + if aspects.intersects(ImageAspects::PLANE_0) { + ImageAspects::PLANE_0 } else { aspects } @@ -1681,12 +1702,8 @@ impl RawImage { #[inline] pub fn subresource_range(&self) -> ImageSubresourceRange { ImageSubresourceRange { - aspects: ImageAspects { - plane0: false, - plane1: false, - plane2: false, - ..self.format.unwrap().aspects() - }, + aspects: self.format.unwrap().aspects() + - (ImageAspects::PLANE_0 | ImageAspects::PLANE_1 | ImageAspects::PLANE_2), mip_levels: 0..self.mip_levels, array_layers: 0..self.dimensions.array_layers(), } @@ -1754,12 +1771,14 @@ impl RawImage { // VUID-vkGetImageSubresourceLayout-aspectMask-00997 // VUID-vkGetImageSubresourceLayout-format-04462 // VUID-vkGetImageSubresourceLayout-format-04463 - if allowed_aspects.depth && allowed_aspects.stencil { + if allowed_aspects.contains(ImageAspects::DEPTH | ImageAspects::STENCIL) { return Err(ImageError::DepthStencilFormatsNotSupported); } - if allowed_aspects.plane0 || allowed_aspects.plane1 || allowed_aspects.plane2 { - allowed_aspects.color = false; + if allowed_aspects + .intersects(ImageAspects::PLANE_0 | ImageAspects::PLANE_1 | ImageAspects::PLANE_2) + { + allowed_aspects -= ImageAspects::COLOR; } // VUID-vkGetImageSubresourceLayout-format-04461 @@ -1768,7 +1787,7 @@ impl RawImage { // VUID-vkGetImageSubresourceLayout-format-04464 // VUID-vkGetImageSubresourceLayout-format-01581 // VUID-vkGetImageSubresourceLayout-format-01582 - if !allowed_aspects.contains(&aspect.into()) { + if !allowed_aspects.contains(aspect.into()) { return Err(ImageError::AspectNotAllowed { provided_aspect: aspect, allowed_aspects, @@ -1997,7 +2016,7 @@ pub enum ImageMemory { impl Image { fn from_raw(inner: RawImage, memory: ImageMemory) -> Self { 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 aspect_size = mip_level_size * inner.mip_levels as DeviceSize; 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. #[inline] - pub fn format_features(&self) -> &FormatFeatures { - &self.inner.format_features + pub fn format_features(&self) -> FormatFeatures { + self.inner.format_features } /// Returns the number of mipmap levels in the image. @@ -2118,14 +2137,14 @@ impl Image { /// Returns the usage the image was created with. #[inline] - pub fn usage(&self) -> &ImageUsage { - &self.inner.usage + pub fn usage(&self) -> ImageUsage { + self.inner.usage } /// Returns the stencil usage the image was created with. #[inline] - pub fn stencil_usage(&self) -> &ImageUsage { - &self.inner.stencil_usage + pub fn stencil_usage(&self) -> ImageUsage { + self.inner.stencil_usage } /// Returns the sharing the image was created with. @@ -2206,7 +2225,7 @@ impl Image { .format() .unwrap() .aspects() - .contains(&subresource_range.aspects)); + .contains(subresource_range.aspects)); assert!(subresource_range.mip_levels.end <= self.inner.mip_levels); assert!(subresource_range.array_layers.end <= self.inner.dimensions.array_layers()); @@ -2608,7 +2627,7 @@ impl SubresourceRangeIterator { let mut aspect_nums = subresource_range .aspects - .iter() + .into_iter() .map(|aspect| image_aspect_list.iter().position(|&a| a == aspect).unwrap()) .collect::>() .into_iter() @@ -3239,10 +3258,7 @@ mod tests { array_layers: 1, }, format: Some(Format::R8G8B8A8_UNORM), - usage: ImageUsage { - sampled: true, - ..ImageUsage::empty() - }, + usage: ImageUsage::SAMPLED, ..Default::default() }, ) @@ -3262,11 +3278,7 @@ mod tests { array_layers: 1, }, format: Some(Format::R8G8B8A8_UNORM), - usage: ImageUsage { - transient_attachment: true, - color_attachment: true, - ..ImageUsage::empty() - }, + usage: ImageUsage::TRANSIENT_ATTACHMENT | ImageUsage::COLOR_ATTACHMENT, ..Default::default() }, ) @@ -3288,10 +3300,7 @@ mod tests { }, format: Some(Format::R8G8B8A8_UNORM), mip_levels: 0, - usage: ImageUsage { - sampled: true, - ..ImageUsage::empty() - }, + usage: ImageUsage::SAMPLED, ..Default::default() }, ); @@ -3312,10 +3321,7 @@ mod tests { }, format: Some(Format::R8G8B8A8_UNORM), mip_levels: u32::MAX, - usage: ImageUsage { - sampled: true, - ..ImageUsage::empty() - }, + usage: ImageUsage::SAMPLED, ..Default::default() }, ); @@ -3340,10 +3346,7 @@ mod tests { }, format: Some(Format::R8G8B8A8_UNORM), samples: SampleCount::Sample2, - usage: ImageUsage { - storage: true, - ..ImageUsage::empty() - }, + usage: ImageUsage::STORAGE, ..Default::default() }, ); @@ -3371,10 +3374,7 @@ mod tests { array_layers: 1, }, format: Some(Format::ASTC_5x4_UNORM_BLOCK), - usage: ImageUsage { - color_attachment: true, - ..ImageUsage::empty() - }, + usage: ImageUsage::COLOR_ATTACHMENT, ..Default::default() }, ); @@ -3402,11 +3402,7 @@ mod tests { array_layers: 1, }, format: Some(Format::R8G8B8A8_UNORM), - usage: ImageUsage { - transient_attachment: true, - sampled: true, - ..ImageUsage::empty() - }, + usage: ImageUsage::TRANSIENT_ATTACHMENT | ImageUsage::SAMPLED, ..Default::default() }, ); @@ -3420,20 +3416,14 @@ mod tests { let res = RawImage::new( device, ImageCreateInfo { - flags: ImageCreateFlags { - cube_compatible: true, - ..ImageCreateFlags::empty() - }, + flags: ImageCreateFlags::CUBE_COMPATIBLE, dimensions: ImageDimensions::Dim2d { width: 32, height: 64, array_layers: 1, }, format: Some(Format::R8G8B8A8_UNORM), - usage: ImageUsage { - sampled: true, - ..ImageUsage::empty() - }, + usage: ImageUsage::SAMPLED, ..Default::default() }, ); @@ -3449,15 +3439,12 @@ mod tests { #[allow(clippy::erasing_op, clippy::identity_op)] fn subresource_range_iterator() { // A fictitious set of aspects that no real image would actually ever have. - let image_aspect_list: SmallVec<[ImageAspect; 4]> = ImageAspects { - color: true, - depth: true, - stencil: true, - plane0: true, - ..ImageAspects::empty() - } - .iter() - .collect(); + let image_aspect_list: SmallVec<[ImageAspect; 4]> = (ImageAspects::COLOR + | ImageAspects::DEPTH + | ImageAspects::STENCIL + | ImageAspects::PLANE_0) + .into_iter() + .collect(); let image_mip_levels = 6; let image_array_layers = 8; @@ -3467,13 +3454,10 @@ mod tests { // Whole image let mut iter = SubresourceRangeIterator::new( ImageSubresourceRange { - aspects: ImageAspects { - color: true, - depth: true, - stencil: true, - plane0: true, - ..ImageAspects::empty() - }, + aspects: ImageAspects::COLOR + | ImageAspects::DEPTH + | ImageAspects::STENCIL + | ImageAspects::PLANE_0, mip_levels: 0..6, array_layers: 0..8, }, @@ -3490,13 +3474,7 @@ mod tests { // Only some aspects let mut iter = SubresourceRangeIterator::new( ImageSubresourceRange { - aspects: ImageAspects { - color: true, - depth: true, - stencil: false, - plane0: true, - ..ImageAspects::empty() - }, + aspects: ImageAspects::COLOR | ImageAspects::DEPTH | ImageAspects::PLANE_0, mip_levels: 0..6, array_layers: 0..8, }, @@ -3514,13 +3492,7 @@ mod tests { // Two aspects, and only some of the mip levels let mut iter = SubresourceRangeIterator::new( ImageSubresourceRange { - aspects: ImageAspects { - color: false, - depth: true, - stencil: true, - plane0: false, - ..ImageAspects::empty() - }, + aspects: ImageAspects::DEPTH | ImageAspects::STENCIL, mip_levels: 2..4, array_layers: 0..8, }, @@ -3537,13 +3509,8 @@ mod tests { // One aspect, one mip level, only some of the array layers let mut iter = SubresourceRangeIterator::new( ImageSubresourceRange { - aspects: ImageAspects { - color: true, - depth: false, - stencil: false, - plane0: false, - ..ImageAspects::empty() - }, + aspects: ImageAspects::COLOR, + mip_levels: 0..1, array_layers: 2..4, }, @@ -3563,13 +3530,7 @@ mod tests { // Two aspects, two mip levels, only some of the array layers let mut iter = SubresourceRangeIterator::new( ImageSubresourceRange { - aspects: ImageAspects { - color: false, - depth: true, - stencil: true, - plane0: false, - ..ImageAspects::empty() - }, + aspects: ImageAspects::DEPTH | ImageAspects::STENCIL, mip_levels: 2..4, array_layers: 6..8, }, diff --git a/vulkano/src/image/traits.rs b/vulkano/src/image/traits.rs index fa3dc4ed..5b5a6a50 100644 --- a/vulkano/src/image/traits.rs +++ b/vulkano/src/image/traits.rs @@ -75,7 +75,7 @@ pub unsafe trait ImageAccess: DeviceOwned + Send + Sync { /// Returns the features supported by the image's format. #[inline] - fn format_features(&self) -> &FormatFeatures { + fn format_features(&self) -> FormatFeatures { self.inner().image.format_features() } @@ -93,13 +93,13 @@ pub unsafe trait ImageAccess: DeviceOwned + Send + Sync { /// Returns the usage the image was created with. #[inline] - fn usage(&self) -> &ImageUsage { + fn usage(&self) -> ImageUsage { self.inner().image.usage() } /// Returns the stencil usage the image was created with. #[inline] - fn stencil_usage(&self) -> &ImageUsage { + fn stencil_usage(&self) -> ImageUsage { self.inner().image.stencil_usage() } @@ -115,12 +115,8 @@ pub unsafe trait ImageAccess: DeviceOwned + Send + Sync { #[inline] fn subresource_range(&self) -> ImageSubresourceRange { ImageSubresourceRange { - aspects: ImageAspects { - plane0: false, - plane1: false, - plane2: false, - ..self.format().aspects() - }, + aspects: self.format().aspects() + - (ImageAspects::PLANE_0 | ImageAspects::PLANE_1 | ImageAspects::PLANE_2), mip_levels: 0..self.mip_levels(), array_layers: 0..self.dimensions().array_layers(), } diff --git a/vulkano/src/image/usage.rs b/vulkano/src/image/usage.rs index 64b025fd..c663dd95 100644 --- a/vulkano/src/image/usage.rs +++ b/vulkano/src/image/usage.rs @@ -10,29 +10,30 @@ use crate::macros::vulkan_bitflags; vulkan_bitflags! { + #[non_exhaustive] + /// 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. - #[non_exhaustive] ImageUsage = ImageUsageFlags(u32); /// 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. - transfer_dst = TRANSFER_DST, + TRANSFER_DST = TRANSFER_DST, /// 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. - storage = STORAGE, + STORAGE = STORAGE, /// 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. - 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. /// 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` /// and `input_attachment` can be true as well. The rest must be false or an error will be /// 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. - input_attachment = INPUT_ATTACHMENT, + INPUT_ATTACHMENT = INPUT_ATTACHMENT, /* // TODO: document - video_decode_dst = VIDEO_DECODE_DST_KHR { + VIDEO_DECODE_DST = VIDEO_DECODE_DST_KHR { device_extensions: [khr_video_decode_queue], }, // TODO: document - video_decode_src = VIDEO_DECODE_SRC_KHR { + VIDEO_DECODE_SRC = VIDEO_DECODE_SRC_KHR { device_extensions: [khr_video_decode_queue], }, // TODO: document - video_decode_dpb = VIDEO_DECODE_DPB_KHR { + VIDEO_DECODE_DPB = VIDEO_DECODE_DPB_KHR { device_extensions: [khr_video_decode_queue], }, // TODO: document - fragment_density_map = FRAGMENT_DENSITY_MAP_EXT { + FRAGMENT_DENSITY_MAP = FRAGMENT_DENSITY_MAP_EXT { device_extensions: [ext_fragment_density_map], }, // 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], }, // TODO: document - video_encode_dst = VIDEO_ENCODE_DST_KHR { + VIDEO_ENCODE_DST = VIDEO_ENCODE_DST_KHR { device_extensions: [khr_video_encode_queue], }, // TODO: document - video_encode_src = VIDEO_ENCODE_SRC_KHR { + VIDEO_ENCODE_SRC = VIDEO_ENCODE_SRC_KHR { device_extensions: [khr_video_encode_queue], }, // TODO: document - video_encode_dpb = VIDEO_ENCODE_DPB_KHR { + VIDEO_ENCODE_DPB = VIDEO_ENCODE_DPB_KHR { device_extensions: [khr_video_encode_queue], }, // TODO: document - invocation_mask = INVOCATION_MASK_HUAWEI { + INVOCATION_MASK = INVOCATION_MASK_HUAWEI { device_extensions: [huawei_invocation_mask], }, */ diff --git a/vulkano/src/image/view.rs b/vulkano/src/image/view.rs index de90bf3f..718505c6 100644 --- a/vulkano/src/image/view.rs +++ b/vulkano/src/image/view.rs @@ -19,7 +19,7 @@ use super::{ use crate::{ device::{Device, DeviceOwned}, format::{ChromaSampling, Format, FormatFeatures}, - image::{ImageAspects, ImageTiling, ImageType, SampleCount}, + image::{ImageAspects, ImageCreateFlags, ImageTiling, ImageType, SampleCount}, macros::vulkan_enum, sampler::{ycbcr::SamplerYcbcrConversion, ComponentMapping}, OomError, RequirementNotMet, RequiresOneOf, Version, VulkanError, VulkanObject, @@ -145,32 +145,24 @@ where // VUID-VkImageSubresourceRange-aspectMask-parameter subresource_range.aspects.validate_device(device)?; - { - let ImageAspects { - color, - depth, - stencil, - metadata, - plane0, - plane1, - plane2, - memory_plane0, - memory_plane1, - memory_plane2, - _ne: _, - } = subresource_range.aspects; - - assert!(!(metadata || memory_plane0 || memory_plane1 || memory_plane2)); - 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) - }); - } + assert!(!subresource_range.aspects.intersects( + ImageAspects::METADATA + | ImageAspects::MEMORY_PLANE_0 + | ImageAspects::MEMORY_PLANE_1 + | ImageAspects::MEMORY_PLANE_2 + )); + assert!({ + subresource_range.aspects.count() == 1 + || subresource_range + .aspects + .contains(ImageAspects::DEPTH | ImageAspects::STENCIL) + && !subresource_range.aspects.intersects( + ImageAspects::COLOR + | ImageAspects::PLANE_0 + | ImageAspects::PLANE_1 + | ImageAspects::PLANE_2, + ) + }); // Get format features let format_features = unsafe { Self::get_format_features(format, image_inner) }; @@ -180,7 +172,7 @@ where .format() .unwrap() .aspects() - .contains(&subresource_range.aspects) + .contains(subresource_range.aspects) { return Err(ImageViewCreationError::ImageAspectsNotCompatible { aspects: subresource_range.aspects, @@ -203,7 +195,9 @@ where // VUID-VkImageViewCreateInfo-image-01003 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); } @@ -231,7 +225,10 @@ where && (view_type == ImageViewType::Dim2d || view_type == ImageViewType::Dim2dArray) { // VUID-VkImageViewCreateInfo-image-01005 - if !image_inner.flags().array_2d_compatible { + if !image_inner + .flags() + .intersects(ImageCreateFlags::ARRAY_2D_COMPATIBLE) + { return Err(ImageViewCreationError::ImageNotArray2dCompatible); } @@ -299,7 +296,7 @@ where // VUID-VkImageViewCreateInfo-pNext-02662 // VUID-VkImageViewCreateInfo-pNext-02663 // VUID-VkImageViewCreateInfo-pNext-02664 - if !default_usage.contains(&usage) { + if !default_usage.contains(usage) { return Err(ImageViewCreationError::UsageNotSupportedByImage { usage, supported_usage: default_usage, @@ -308,43 +305,54 @@ where } // VUID-VkImageViewCreateInfo-image-04441 - if !(image_inner.usage().sampled - || image_inner.usage().storage - || image_inner.usage().color_attachment - || image_inner.usage().depth_stencil_attachment - || image_inner.usage().input_attachment - || image_inner.usage().transient_attachment) - { + if !image_inner.usage().intersects( + ImageUsage::SAMPLED + | ImageUsage::STORAGE + | ImageUsage::COLOR_ATTACHMENT + | ImageUsage::DEPTH_STENCIL_ATTACHMENT + | ImageUsage::INPUT_ATTACHMENT + | ImageUsage::TRANSIENT_ATTACHMENT, + ) { return Err(ImageViewCreationError::ImageMissingUsage); } // 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" }); } // 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" }); } // 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 { usage: "color_attachment", }); } // 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 { usage: "depth_stencil_attachment", }); } // VUID-VkImageViewCreateInfo-usage-02652 - if usage.input_attachment - && !(format_features.color_attachment || format_features.depth_stencil_attachment) + if usage.intersects(ImageUsage::INPUT_ATTACHMENT) + && !format_features.intersects( + FormatFeatures::COLOR_ATTACHMENT | FormatFeatures::DEPTH_STENCIL_ATTACHMENT, + ) { return Err(ImageViewCreationError::FormatUsageNotSupported { usage: "input_attachment", @@ -355,9 +363,11 @@ where if Some(format) != image_inner.format() { // 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() - && subresource_range.aspects.color + && subresource_range.aspects.intersects(ImageAspects::COLOR) { return Err(ImageViewCreationError::FormatNotCompatible); } @@ -370,10 +380,9 @@ where && format.components() != image_inner.format().unwrap().components() { return Err(ImageViewCreationError::RequirementNotMet { - required_for: - "this device is a portability subset device, and the format of the image \ - view does not have the same components and number of bits per component as \ - the parent image", + required_for: "this device is a portability subset device, and the format of \ + the image view does not have the same components and number of bits per \ + component as the parent image", requires_one_of: RequiresOneOf { features: &["image_view_format_reinterpretation"], ..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 if !(format.compatibility() == image_inner.format().unwrap().compatibility() || format.block_size() == image_inner.format().unwrap().block_size()) @@ -411,11 +423,11 @@ where return Err(ImageViewCreationError::FormatNotCompatible); } } else { - let plane = if subresource_range.aspects.plane0 { + let plane = if subresource_range.aspects.intersects(ImageAspects::PLANE_0) { 0 - } else if subresource_range.aspects.plane1 { + } else if subresource_range.aspects.intersects(ImageAspects::PLANE_1) { 1 - } else if subresource_range.aspects.plane2 { + } else if subresource_range.aspects.intersects(ImageAspects::PLANE_2) { 2 } else { unreachable!() @@ -660,7 +672,7 @@ where format: image_inner.format(), image_type: image.dimensions().image_type(), tiling: image_inner.tiling(), - usage: *image_inner.usage(), + usage: image_inner.usage(), image_view_type: Some(view_type), ..Default::default() })?; @@ -689,19 +701,15 @@ where // https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VkImageViewCreateInfo.html#_description fn get_default_usage(aspects: ImageAspects, image: &Image) -> ImageUsage { - let has_stencil_aspect = aspects.stencil; - let has_non_stencil_aspect = !(ImageAspects { - stencil: false, - ..aspects - }) - .is_empty(); + let has_stencil_aspect = aspects.intersects(ImageAspects::STENCIL); + let has_non_stencil_aspect = !(aspects - ImageAspects::STENCIL).is_empty(); if has_stencil_aspect && has_non_stencil_aspect { - *image.usage() & *image.stencil_usage() + image.usage() & image.stencil_usage() } else if has_stencil_aspect { - *image.stencil_usage() + image.stencil_usage() } else if has_non_stencil_aspect { - *image.usage() + image.usage() } else { unreachable!() } @@ -711,7 +719,7 @@ where unsafe fn get_format_features(format: Format, image: &Image) -> FormatFeatures { 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. let format_properties = device.physical_device().format_properties_unchecked(format); @@ -720,28 +728,34 @@ where ImageTiling::Linear => format_properties.linear_tiling_features, } } else { - *image.format_features() + image.format_features() }; - if device.enabled_extensions().khr_format_feature_flags2 { - format_features - } else { - let is_without_format = format.shader_storage_image_without_format(); + if !device.enabled_extensions().khr_format_feature_flags2 { + if format.type_color().is_none() + && format_features.intersects(FormatFeatures::SAMPLED_IMAGE) + { + format_features |= FormatFeatures::SAMPLED_IMAGE_DEPTH_COMPARISON; + } - FormatFeatures { - sampled_image_depth_comparison: format.type_color().is_none() - && format_features.sampled_image, - storage_read_without_format: is_without_format - && device - .enabled_features() - .shader_storage_image_read_without_format, - storage_write_without_format: is_without_format - && device - .enabled_features() - .shader_storage_image_write_without_format, - ..format_features + if format.shader_storage_image_without_format() { + if device + .enabled_features() + .shader_storage_image_read_without_format + { + format_features |= FormatFeatures::STORAGE_READ_WITHOUT_FORMAT; + } + + if device + .enabled_features() + .shader_storage_image_write_without_format + { + format_features |= FormatFeatures::STORAGE_WRITE_WITHOUT_FORMAT; + } } } + + format_features } /// Returns the wrapped image that this image view was created from. @@ -1146,9 +1160,38 @@ impl From for ImageViewCreationError { } vulkan_enum! { - /// The geometry type of an image view. #[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 Dim1d = TYPE_1D, @@ -1172,35 +1215,6 @@ vulkan_enum! { 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. pub unsafe trait ImageViewAbstract: VulkanObject + DeviceOwned + Debug + Send + Sync @@ -1254,7 +1268,7 @@ pub unsafe trait ImageViewAbstract: fn format(&self) -> Option; /// 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. fn sampler_ycbcr_conversion(&self) -> Option<&Arc>; @@ -1263,7 +1277,7 @@ pub unsafe trait ImageViewAbstract: fn subresource_range(&self) -> &ImageSubresourceRange; /// Returns the usage of the image view. - fn usage(&self) -> &ImageUsage; + fn usage(&self) -> ImageUsage; /// Returns the [`ImageViewType`] of this image view. fn view_type(&self) -> ImageViewType; @@ -1293,8 +1307,8 @@ where self.format } - fn format_features(&self) -> &FormatFeatures { - &self.format_features + fn format_features(&self) -> FormatFeatures { + self.format_features } fn sampler_ycbcr_conversion(&self) -> Option<&Arc> { @@ -1305,8 +1319,8 @@ where &self.subresource_range } - fn usage(&self) -> &ImageUsage { - &self.usage + fn usage(&self) -> ImageUsage { + self.usage } fn view_type(&self) -> ImageViewType { @@ -1341,8 +1355,8 @@ unsafe impl ImageViewAbstract for ImageView { } #[inline] - fn format_features(&self) -> &FormatFeatures { - &self.format_features + fn format_features(&self) -> FormatFeatures { + self.format_features } #[inline] @@ -1356,8 +1370,8 @@ unsafe impl ImageViewAbstract for ImageView { } #[inline] - fn usage(&self) -> &ImageUsage { - &self.usage + fn usage(&self) -> ImageUsage { + self.usage } #[inline] diff --git a/vulkano/src/instance/debug.rs b/vulkano/src/instance/debug.rs index 7452417d..7e5a75e8 100644 --- a/vulkano/src/instance/debug.rs +++ b/vulkano/src/instance/debug.rs @@ -105,7 +105,7 @@ impl DebugUtilsMessenger { if !instance.enabled_extensions().ext_debug_utils { return Err(DebugUtilsMessengerCreationError::RequirementNotMet { - required_for: "`DebugUtilsMessenger`", + required_for: "`DebugUtilsMessenger::new`", requires_one_of: RequiresOneOf { instance_extensions: &["ext_debug_utils"], ..Default::default() @@ -319,15 +319,8 @@ impl DebugUtilsMessengerCreateInfo { #[inline] pub fn user_callback(user_callback: UserCallback) -> Self { Self { - message_severity: DebugUtilsMessageSeverity { - error: true, - warning: true, - ..DebugUtilsMessageSeverity::empty() - }, - message_type: DebugUtilsMessageType { - general: true, - ..DebugUtilsMessageType::empty() - }, + message_severity: DebugUtilsMessageSeverity::ERROR | DebugUtilsMessageSeverity::WARNING, + message_type: DebugUtilsMessageType::GENERAL, user_callback, _ne: crate::NonExhaustive(()), } @@ -363,36 +356,38 @@ pub struct Message<'a> { } vulkan_bitflags! { - /// Severity of message. #[non_exhaustive] + + /// Severity of message. DebugUtilsMessageSeverity = DebugUtilsMessageSeverityFlagsEXT(u32); /// An error that may cause undefined results, including an application crash. - error = ERROR, + ERROR = ERROR, /// An unexpected use. - warning = WARNING, + WARNING = WARNING, /// An informational message that may be handy when debugging an application. - information = INFO, + INFO = INFO, /// Diagnostic information from the loader and layers. - verbose = VERBOSE, + VERBOSE = VERBOSE, } vulkan_bitflags! { - /// Type of message. #[non_exhaustive] + + /// Type of message. DebugUtilsMessageType = DebugUtilsMessageTypeFlagsEXT(u32); /// Specifies that some general event has occurred. - general = GENERAL, + GENERAL = GENERAL, /// Specifies that something has occurred during validation against the vulkan specification - validation = VALIDATION, + VALIDATION = VALIDATION, /// Specifies a potentially non-optimal use of Vulkan - performance = PERFORMANCE, + PERFORMANCE = PERFORMANCE, } /// A label to associate with a span of work in a queue. @@ -428,6 +423,8 @@ impl Default for DebugUtilsLabel { } vulkan_enum! { + #[non_exhaustive] + /// Features of the validation layer to enable. ValidationFeatureEnable = ValidationFeatureEnableEXT(i32); @@ -461,6 +458,8 @@ vulkan_enum! { } vulkan_enum! { + #[non_exhaustive] + /// Features of the validation layer to disable. ValidationFeatureDisable = ValidationFeatureDisableEXT(i32); @@ -529,16 +528,10 @@ mod tests { DebugUtilsMessenger::new( instance, DebugUtilsMessengerCreateInfo { - message_severity: DebugUtilsMessageSeverity { - error: true, - ..DebugUtilsMessageSeverity::empty() - }, - message_type: DebugUtilsMessageType { - general: true, - validation: true, - performance: true, - ..DebugUtilsMessageType::empty() - }, + message_severity: DebugUtilsMessageSeverity::ERROR, + message_type: DebugUtilsMessageType::GENERAL + | DebugUtilsMessageType::VALIDATION + | DebugUtilsMessageType::PERFORMANCE, ..DebugUtilsMessengerCreateInfo::user_callback(Arc::new(|_| {})) }, ) diff --git a/vulkano/src/instance/mod.rs b/vulkano/src/instance/mod.rs index 35cb1b64..ba375ae8 100644 --- a/vulkano/src/instance/mod.rs +++ b/vulkano/src/instance/mod.rs @@ -414,7 +414,8 @@ impl Instance { if !enabled_validation_features.is_empty() || !disabled_validation_features.is_empty() { if !enabled_extensions.ext_validation_features { 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 { instance_extensions: &["ext_validation_features"], ..Default::default() @@ -464,7 +465,7 @@ impl Instance { // VUID-VkInstanceCreateInfo-pNext-04926 if !enabled_extensions.ext_debug_utils { 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 { instance_extensions: &["ext_debug_utils"], ..Default::default() diff --git a/vulkano/src/lib.rs b/vulkano/src/lib.rs index ba2958ce..a7a083de 100644 --- a/vulkano/src/lib.rs +++ b/vulkano/src/lib.rs @@ -62,7 +62,11 @@ //! //#![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. #![allow( clippy::collapsible_else_if, diff --git a/vulkano/src/macros.rs b/vulkano/src/macros.rs index efd6c561..eaebaf67 100644 --- a/vulkano/src/macros.rs +++ b/vulkano/src/macros.rs @@ -10,7 +10,9 @@ macro_rules! vulkan_bitflags { { $(#[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])* @@ -18,23 +20,19 @@ macro_rules! vulkan_bitflags { )+ } => { $(#[doc = $ty_doc])* - #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] - pub struct $ty { - $( - $(#[doc = $flag_doc])* - pub $flag_name: bool, - )+ - } + #[derive(Clone, Copy, PartialEq, Eq, Hash)] + pub struct $ty($repr); 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.")] #[inline] pub const fn empty() -> Self { - Self { - $( - $flag_name: false, - )+ - } + Self(0) } #[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.")] #[inline] pub const fn all() -> Self { - Self { - $( - $flag_name: true, - )+ - } + Self(Self::all_raw()) + } + + const fn all_raw() -> $repr { + 0 + $( + | ash::vk::$ty_ffi::$flag_name_ffi.as_raw() + )* } /// Returns whether no flags are set in `self`. #[inline] - pub const fn is_empty(&self) -> bool { - !( - $( - self.$flag_name - )||+ - ) + pub const fn is_empty(self) -> bool { + self.0 == 0 } /// Returns whether any flags are set in both `self` and `other`. #[inline] - pub const fn intersects(&self, other: &Self) -> bool { - $( - (self.$flag_name && other.$flag_name) - )||+ + pub const fn intersects(self, #[allow(unused_variables)] other: Self) -> bool { + self.0 & other.0 != 0 } /// Returns whether all flags in `other` are set in `self`. #[inline] - pub const fn contains(&self, other: &Self) -> bool { - $( - (self.$flag_name || !other.$flag_name) - )&&+ + pub const fn contains(self, #[allow(unused_variables)] other: Self) -> bool { + self.0 & other.0 == other.0 } /// Returns the union of `self` and `other`. #[inline] - pub const fn union(&self, other: &Self) -> Self { - Self { - $( - $flag_name: (self.$flag_name || other.$flag_name), - )+ - } + pub const fn union(self, #[allow(unused_variables)] other: Self) -> Self { + Self(self.0 | other.0) } /// Returns the intersection of `self` and `other`. #[inline] - pub const fn intersection(&self, other: &Self) -> Self { - Self { - $( - $flag_name: (self.$flag_name && other.$flag_name), - )+ - } + pub const fn intersection(self, #[allow(unused_variables)] other: Self) -> Self { + Self(self.0 & other.0) } /// Returns `self` without the flags set in `other`. #[inline] - pub const fn difference(&self, other: &Self) -> Self { - Self { - $( - $flag_name: (self.$flag_name && !other.$flag_name), - )+ - } + pub const fn difference(self, #[allow(unused_variables)] other: Self) -> Self { + Self(self.0 & !other.0) } - /// 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] - pub const fn symmetric_difference(&self, other: &Self) -> Self { - Self { - $( - $flag_name: (self.$flag_name ^ other.$flag_name), - )+ - } + pub const fn symmetric_difference(self, #[allow(unused_variables)] other: Self) -> Self { + Self(self.0 ^ other.0) } /// Returns the flags not in `self`. #[inline] - pub const fn complement(&self) -> Self { - Self { - $( - $flag_name: !self.$flag_name, - )+ + pub const fn complement(self) -> Self { + Self(!self.0 & Self::all_raw()) + } + + $( $($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 { #[inline] fn from(val: $ty) -> Self { - let mut result = ash::vk::$ty_ffi::empty(); - $( - if val.$flag_name { result |= ash::vk::$ty_ffi::$flag_name_ffi } - )+ - result + ash::vk::$ty_ffi::from_raw(val.0) } } impl From for $ty { #[inline] fn from(val: ash::vk::$ty_ffi) -> Self { - Self { - $( - $flag_name: val.intersects(ash::vk::$ty_ffi::$flag_name_ffi), - )+ - } - } - } - - impl Default for $ty { - #[inline] - fn default() -> Self { - Self { - $( - $flag_name: false, - )+ - } + Self(val.as_raw() & Self::all_raw()) } } @@ -169,14 +156,14 @@ macro_rules! vulkan_bitflags { #[inline] fn bitand(self, rhs: Self) -> Self { - self.intersection(&rhs) + self.intersection(rhs) } } impl std::ops::BitAndAssign for $ty { #[inline] fn bitand_assign(&mut self, rhs: Self) { - *self = self.intersection(&rhs); + *self = self.intersection(rhs); } } @@ -185,14 +172,14 @@ macro_rules! vulkan_bitflags { #[inline] fn bitor(self, rhs: Self) -> Self { - self.union(&rhs) + self.union(rhs) } } impl std::ops::BitOrAssign for $ty { #[inline] fn bitor_assign(&mut self, rhs: Self) { - *self = self.union(&rhs); + *self = self.union(rhs); } } @@ -201,14 +188,14 @@ macro_rules! vulkan_bitflags { #[inline] fn bitxor(self, rhs: Self) -> Self { - self.symmetric_difference(&rhs) + self.symmetric_difference(rhs) } } impl std::ops::BitXorAssign for $ty { #[inline] 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] fn sub(self, rhs: Self) -> Self { - self.difference(&rhs) + self.difference(rhs) } } impl std::ops::SubAssign for $ty { #[inline] 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] - $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])* @@ -256,25 +246,19 @@ macro_rules! vulkan_bitflags { )* } => { $(#[doc = $ty_doc])* - #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] - pub struct $ty { - $( - $(#[doc = $flag_doc])* - pub $flag_name: bool, - )* - pub _ne: crate::NonExhaustive, - } + #[derive(Clone, Copy, PartialEq, Eq, Hash)] + pub struct $ty($repr); 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.")] #[inline] pub const fn empty() -> Self { - Self { - $( - $flag_name: false, - )* - _ne: crate::NonExhaustive(()), - } + Self(0) } #[deprecated(since = "0.31.0", note = "Use `empty` instead.")] @@ -284,78 +268,59 @@ macro_rules! vulkan_bitflags { 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`. #[inline] - pub const fn is_empty(&self) -> bool { - !( - false - $( - || self.$flag_name - )* - - ) + pub const fn is_empty(self) -> bool { + self.0 == 0 } /// Returns whether any flags are set in both `self` and `other`. #[inline] - pub const fn intersects(&self, #[allow(unused_variables)] other: &Self) -> bool { - false - $( - || (self.$flag_name && other.$flag_name) - )* + pub const fn intersects(self, #[allow(unused_variables)] other: Self) -> bool { + self.0 & other.0 != 0 } /// Returns whether all flags in `other` are set in `self`. #[inline] - pub const fn contains(&self, #[allow(unused_variables)] other: &Self) -> bool { - true - $( - && (self.$flag_name || !other.$flag_name) - )* + pub const fn contains(self, #[allow(unused_variables)] other: Self) -> bool { + self.0 & other.0 == other.0 } /// Returns the union of `self` and `other`. #[inline] - pub const fn union(&self, #[allow(unused_variables)] other: &Self) -> Self { - Self { - $( - $flag_name: (self.$flag_name || other.$flag_name), - )* - _ne: crate::NonExhaustive(()), - } + pub const fn union(self, #[allow(unused_variables)] other: Self) -> Self { + Self(self.0 | other.0) } /// Returns the intersection of `self` and `other`. #[inline] - pub const fn intersection(&self, #[allow(unused_variables)] other: &Self) -> Self { - Self { - $( - $flag_name: (self.$flag_name && other.$flag_name), - )* - _ne: crate::NonExhaustive(()), - } + pub const fn intersection(self, #[allow(unused_variables)] other: Self) -> Self { + Self(self.0 & other.0) } /// Returns `self` without the flags set in `other`. #[inline] - pub const fn difference(&self, #[allow(unused_variables)] other: &Self) -> Self { - Self { - $( - $flag_name: (self.$flag_name ^ other.$flag_name), - )* - _ne: crate::NonExhaustive(()), - } + pub const fn difference(self, #[allow(unused_variables)] other: Self) -> Self { + Self(self.0 & !other.0) } - /// 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] - pub const fn symmetric_difference(&self, #[allow(unused_variables)] other: &Self) -> Self { - Self { - $( - $flag_name: (self.$flag_name ^ other.$flag_name), - )* - _ne: crate::NonExhaustive(()), - } + pub const fn symmetric_difference(self, #[allow(unused_variables)] other: Self) -> Self { + Self(self.0 ^ other.0) } #[allow(dead_code)] @@ -365,7 +330,7 @@ macro_rules! vulkan_bitflags { ) -> Result<(), crate::RequirementNotMet> { $( $( - if self.$flag_name && ![ + if self.intersects(Self::$flag_name) && ![ $( device.api_version() >= crate::Version::$api_version, )? @@ -403,7 +368,7 @@ macro_rules! vulkan_bitflags { ) -> Result<(), crate::RequirementNotMet> { $( $( - if self.$flag_name && ![ + if self.intersects(Self::$flag_name) && ![ $( physical_device.api_version() >= crate::Version::$api_version, )? @@ -441,7 +406,7 @@ macro_rules! vulkan_bitflags { ) -> Result<(), crate::RequirementNotMet> { $( $( - if self.$flag_name && ![ + if self.intersects(Self::$flag_name) && ![ $( instance.api_version() >= crate::Version::$api_version, )? @@ -463,41 +428,52 @@ macro_rules! vulkan_bitflags { Ok(()) } - } - impl From<$ty> for ash::vk::$ty_ffi { - #[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 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(()), - } - } + $( $($impls)* )? } impl Default for $ty { #[inline] fn default() -> Self { - Self { - $( - $flag_name: false, - )* - _ne: crate::NonExhaustive(()), + 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 { + #[inline] + fn from(val: $ty) -> Self { + ash::vk::$ty_ffi::from_raw(val.0) + } + } + + impl From 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] fn bitand(self, rhs: Self) -> Self { - self.intersection(&rhs) + self.intersection(rhs) } } impl std::ops::BitAndAssign for $ty { #[inline] fn bitand_assign(&mut self, rhs: Self) { - *self = self.intersection(&rhs); + *self = self.intersection(rhs); } } @@ -522,14 +498,14 @@ macro_rules! vulkan_bitflags { #[inline] fn bitor(self, rhs: Self) -> Self { - self.union(&rhs) + self.union(rhs) } } impl std::ops::BitOrAssign for $ty { #[inline] fn bitor_assign(&mut self, rhs: Self) { - *self = self.union(&rhs); + *self = self.union(rhs); } } @@ -538,14 +514,14 @@ macro_rules! vulkan_bitflags { #[inline] fn bitxor(self, rhs: Self) -> Self { - self.symmetric_difference(&rhs) + self.symmetric_difference(rhs) } } impl std::ops::BitXorAssign for $ty { #[inline] 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] fn sub(self, rhs: Self) -> Self { - self.difference(&rhs) + self.difference(rhs) } } impl std::ops::SubAssign for $ty { #[inline] 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 { { $(#[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])* @@ -587,6 +565,12 @@ macro_rules! vulkan_enum { )+ } + $( + impl $ty { + $($impls)* + } + )? + impl From<$ty> for ash::vk::$ty_ffi { #[inline] fn from(val: $ty) -> Self { @@ -610,9 +594,12 @@ macro_rules! vulkan_enum { }; { - $(#[doc = $ty_doc:literal])* #[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])* @@ -758,6 +745,10 @@ macro_rules! vulkan_enum { Ok(()) } + + $( + $($impls)* + )? } 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(iter: T) -> Self where T: IntoIterator { + 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, + { $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}; diff --git a/vulkano/src/memory/allocator/mod.rs b/vulkano/src/memory/allocator/mod.rs index 40fe0388..f060dd3b 100644 --- a/vulkano/src/memory/allocator/mod.rs +++ b/vulkano/src/memory/allocator/mod.rs @@ -353,17 +353,17 @@ impl From for MemoryTypeFilter { match usage { MemoryUsage::GpuOnly => { - filter.preferred_flags.device_local = true; - filter.not_preferred_flags.host_visible = true; + filter.preferred_flags |= MemoryPropertyFlags::DEVICE_LOCAL; + filter.not_preferred_flags |= MemoryPropertyFlags::HOST_VISIBLE; } MemoryUsage::Upload => { - filter.required_flags.host_visible = true; - filter.preferred_flags.device_local = true; - filter.not_preferred_flags.host_cached = true; + filter.required_flags |= MemoryPropertyFlags::HOST_VISIBLE; + filter.preferred_flags |= MemoryPropertyFlags::DEVICE_LOCAL; + filter.not_preferred_flags |= MemoryPropertyFlags::HOST_CACHED; } MemoryUsage::Download => { - filter.required_flags.host_visible = true; - filter.preferred_flags.host_cached = true; + filter.required_flags |= MemoryPropertyFlags::HOST_VISIBLE; + filter.preferred_flags |= MemoryPropertyFlags::HOST_CACHED; } } @@ -464,8 +464,8 @@ impl Default for AllocationCreateInfo<'_> { pub enum MemoryUsage { /// The memory is intended to only be used by the GPU. /// - /// Prefers picking a memory type with the [`device_local`] flag and without the - /// [`host_visible`] flag. + /// Prefers picking a memory type with the [`DEVICE_LOCAL`] flag and + /// without the [`HOST_VISIBLE`] flag. /// /// 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 @@ -473,37 +473,37 @@ pub enum MemoryUsage { /// once and then never again, or resources that are only written and read by the GPU, like /// render targets and intermediary buffers. /// - /// [`device_local`]: MemoryPropertyFlags::device_local - /// [`host_visible`]: MemoryPropertyFlags::host_visible + /// [`DEVICE_LOCAL`]: MemoryPropertyFlags::DEVICE_LOCAL + /// [`HOST_VISIBLE`]: MemoryPropertyFlags::HOST_VISIBLE GpuOnly, /// The memory is intended for upload to the GPU. /// - /// Guarantees picking a memory type with the [`host_visible`] flag. Prefers picking one - /// without the [`host_cached`] flag and with the [`device_local`] flag. + /// Guarantees picking a memory type with the [`HOST_VISIBLE`] flag. Prefers picking one + /// 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, /// 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 /// optimal image. /// - /// [`host_visible`]: MemoryPropertyFlags::host_visible - /// [`host_cached`]: MemoryPropertyFlags::host_cached - /// [`device_local`]: MemoryPropertyFlags::device_local + /// [`HOST_VISIBLE`]: MemoryPropertyFlags::HOST_VISIBLE + /// [`HOST_CACHED`]: MemoryPropertyFlags::HOST_CACHED + /// [`DEVICE_LOCAL`]: MemoryPropertyFlags::DEVICE_LOCAL Upload, /// The memory is intended for download from the GPU. /// - /// Guarantees picking a memory type with the [`host_visible`] flag. Prefers picking one with - /// the [`host_cached`] flag and without the [`device_local`] flag. + /// Guarantees picking a memory type with the [`HOST_VISIBLE`] flag. Prefers picking one with + /// 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 /// need to get the results back to the CPU. That might be compute shading, or image or video /// manipulation, or screenshotting for example. /// - /// [`host_visible`]: MemoryPropertyFlags::host_visible - /// [`host_cached`]: MemoryPropertyFlags::host_cached - /// [`device_local`]: MemoryPropertyFlags::device_local + /// [`HOST_VISIBLE`]: MemoryPropertyFlags::HOST_VISIBLE + /// [`HOST_CACHED`]: MemoryPropertyFlags::HOST_CACHED + /// [`DEVICE_LOCAL`]: MemoryPropertyFlags::DEVICE_LOCAL Download, } @@ -762,7 +762,7 @@ impl GenericMemoryAllocator { && device.enabled_extensions().khr_external_memory) { 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 { api_version: Some(Version::V1_1), device_extensions: &["khr_external_memory"], @@ -853,12 +853,13 @@ impl GenericMemoryAllocator { let mut memory_type_bits = u32::MAX; for (index, MemoryType { property_flags, .. }) in memory_types.iter().enumerate() { - if property_flags.lazily_allocated - || property_flags.protected - || property_flags.device_coherent - || property_flags.device_uncached - || property_flags.rdma_capable - { + if property_flags.intersects( + MemoryPropertyFlags::LAZILY_ALLOCATED + | MemoryPropertyFlags::PROTECTED + | MemoryPropertyFlags::DEVICE_COHERENT + | MemoryPropertyFlags::DEVICE_UNCACHED + | MemoryPropertyFlags::RDMA_CAPABLE, + ) { // VUID-VkMemoryAllocateInfo-memoryTypeIndex-01872 // VUID-vkAllocateMemory-deviceCoherentMemory-02790 // Lazily allocated memory would just cause problems for suballocation in general. @@ -879,9 +880,10 @@ impl GenericMemoryAllocator { allocation_type, dedicated_allocation, export_handle_types, - flags: MemoryAllocateFlags { - device_address, - ..Default::default() + flags: if device_address { + MemoryAllocateFlags::DEVICE_ADDRESS + } else { + MemoryAllocateFlags::empty() }, memory_type_bits, max_allocations, @@ -994,9 +996,9 @@ unsafe impl MemoryAllocator for GenericMemoryAllocator { /// # Panics /// /// - 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. - /// - 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. /// - Panics if `create_info.size` is zero. /// - Panics if `create_info.alignment` is zero. @@ -1012,9 +1014,9 @@ unsafe impl MemoryAllocator for GenericMemoryAllocator { /// - Returns [`SuballocatorBlockSizeExceeded`] if `S` is `PoolAllocator` and /// `create_info.size` is greater than `BLOCK_SIZE`. /// - /// [`protected`]: MemoryPropertyFlags::protected + /// [`PROTECTED`]: MemoryPropertyFlags::PROTECTED /// [`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 /// [`TooManyObjects`]: VulkanError::TooManyObjects /// [`BlockSizeExceeded`]: AllocationCreationError::BlockSizeExceeded @@ -1235,13 +1237,11 @@ unsafe impl MemoryAllocator for GenericMemoryAllocator { /// `create_info.size` is greater than `BLOCK_SIZE` and a dedicated allocation was not /// created. /// - /// [`device_local`]: MemoryPropertyFlags::device_local - /// [`host_visible`]: MemoryPropertyFlags::host_visible /// [`TooManyObjects`]: VulkanError::TooManyObjects - /// [`SuballocatorBlockSizeExceeded`]: AllocationCreationError::SuballocatorBlockSizeExceeded /// [`OutOfPoolMemory`]: AllocationCreationError::OutOfPoolMemory /// [`DedicatedAllocationRequired`]: AllocationCreationError::DedicatedAllocationRequired /// [`BlockSizeExceeded`]: AllocationCreationError::BlockSizeExceeded + /// [`SuballocatorBlockSizeExceeded`]: AllocationCreationError::SuballocatorBlockSizeExceeded fn allocate( &self, create_info: AllocationCreateInfo<'_>, @@ -1549,10 +1549,10 @@ pub struct GenericMemoryAllocatorCreateInfo<'b, 'e> { pub export_handle_types: &'e [ExternalMemoryHandleTypes], /// 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 - /// [`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`] /// 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`. /// - /// [`device_address`]: MemoryAllocateFlags::device_address - /// [`shader_device_address`]: crate::buffer::BufferUsage::shader_device_address + /// [`DEVICE_ADDRESS`]: MemoryAllocateFlags::DEVICE_ADDRESS + /// [`SHADER_DEVICE_ADDRESS`]: crate::buffer::BufferUsage::SHADER_DEVICE_ADDRESS /// [`buffer_device_address`]: crate::device::Features::buffer_device_address /// [`ext_buffer_device_address`]: crate::device::DeviceExtensions::ext_buffer_device_address /// [`khr_device_group`]: crate::device::DeviceExtensions::khr_device_group diff --git a/vulkano/src/memory/allocator/suballocator.rs b/vulkano/src/memory/allocator/suballocator.rs index b312074b..f9d0eba7 100644 --- a/vulkano/src/memory/allocator/suballocator.rs +++ b/vulkano/src/memory/allocator/suballocator.rs @@ -18,7 +18,7 @@ use super::{array_vec::ArrayVec, AllocationCreateInfo, AllocationCreationError}; use crate::{ device::{Device, DeviceOwned}, image::ImageTiling, - memory::DeviceMemory, + memory::{DeviceMemory, MemoryPropertyFlags}, DeviceSize, OomError, VulkanError, VulkanObject, }; use crossbeam_queue::ArrayQueue; @@ -102,7 +102,7 @@ impl MemoryAlloc { [memory_type_index as usize] .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 mut output = MaybeUninit::uninit(); // This is always valid because we are mapping the whole range. @@ -124,9 +124,10 @@ impl MemoryAlloc { None }; - let atom_size = (property_flags.host_visible && !property_flags.host_coherent) - .then_some(physical_device.properties().non_coherent_atom_size) - .and_then(NonZeroU64::new); + let atom_size = (property_flags.intersects(MemoryPropertyFlags::HOST_VISIBLE) + && !property_flags.intersects(MemoryPropertyFlags::HOST_COHERENT)) + .then_some(physical_device.properties().non_coherent_atom_size) + .and_then(NonZeroU64::new); Ok(MemoryAlloc { offset: 0, @@ -225,7 +226,7 @@ impl MemoryAlloc { /// - Panics if `range.end` exceeds `self.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 #[inline] pub unsafe fn invalidate_range(&self, range: Range) -> Result<(), OomError> { @@ -266,7 +267,7 @@ impl MemoryAlloc { /// - Panics if `range.end` exceeds `self.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 #[inline] pub unsafe fn flush_range(&self, range: Range) -> Result<(), OomError> { @@ -605,7 +606,7 @@ unsafe impl DeviceOwned for MemoryAlloc { /// Allocating a region to suballocatate: /// /// ``` -/// use vulkano::memory::{DeviceMemory, MemoryAllocateInfo, MemoryType}; +/// use vulkano::memory::{DeviceMemory, MemoryAllocateInfo, MemoryPropertyFlags, MemoryType}; /// use vulkano::memory::allocator::MemoryAlloc; /// # let device: std::sync::Arc = return; /// @@ -620,7 +621,7 @@ unsafe impl DeviceOwned for MemoryAlloc { /// // 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. /// .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; /// diff --git a/vulkano/src/memory/device_memory.rs b/vulkano/src/memory/device_memory.rs index 5b14a551..7b4d8007 100644 --- a/vulkano/src/memory/device_memory.rs +++ b/vulkano/src/memory/device_memory.rs @@ -10,7 +10,8 @@ use super::{DedicatedAllocation, DedicatedTo}; use crate::{ device::{Device, DeviceOwned}, - macros::{vulkan_bitflags, vulkan_enum}, + macros::{vulkan_bitflags, vulkan_bitflags_enum}, + memory::MemoryPropertyFlags, DeviceSize, OomError, RequirementNotMet, RequiresOneOf, Version, VulkanError, VulkanObject, }; use std::{ @@ -173,10 +174,14 @@ impl DeviceMemory { })?; // 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 { 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 { features: &["protected_memory"], ..Default::default() @@ -197,12 +202,14 @@ impl DeviceMemory { } // 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 { return Err(DeviceMemoryError::RequirementNotMet { 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 { features: &["device_coherent_memory"], ..Default::default() @@ -278,8 +285,8 @@ impl DeviceMemory { } => { if !device.enabled_extensions().khr_external_memory_fd { return Err(DeviceMemoryError::RequirementNotMet { - required_for: - "`allocate_info.import_info` is `Some(MemoryImportInfo::Fd)`", + required_for: "`allocate_info.import_info` is \ + `Some(MemoryImportInfo::Fd)`", requires_one_of: RequiresOneOf { device_extensions: &["khr_external_memory_fd"], ..Default::default() @@ -330,8 +337,8 @@ impl DeviceMemory { } => { if !device.enabled_extensions().khr_external_memory_win32 { return Err(DeviceMemoryError::RequirementNotMet { - required_for: - "`allocate_info.import_info` is `Some(MemoryImportInfo::Win32)`", + required_for: "`allocate_info.import_info` is \ + `Some(MemoryImportInfo::Win32)`", requires_one_of: RequiresOneOf { device_extensions: &["khr_external_memory_win32"], ..Default::default() @@ -390,11 +397,12 @@ impl DeviceMemory { }); } - if flags.device_address { + if flags.intersects(MemoryAllocateFlags::DEVICE_ADDRESS) { // VUID-VkMemoryAllocateInfo-flags-03331 if !device.enabled_features().buffer_device_address { 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 { features: &["buffer_device_address"], ..Default::default() @@ -404,7 +412,8 @@ impl DeviceMemory { if device.enabled_extensions().ext_buffer_device_address { 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 { api_version: Some(Version::V1_2), 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 /// already out-of-date. /// - /// `self` must have been allocated from a memory type that has the - /// [`lazily_allocated`](crate::memory::MemoryPropertyFlags::lazily_allocated) flag set. + /// `self` must have been allocated from a memory type that has the [`LAZILY_ALLOCATED`] flag + /// set. + /// + /// [`LAZILY_ALLOCATED`]: crate::memory::MemoryPropertyFlags::LAZILY_ALLOCATED #[inline] pub fn commitment(&self) -> Result { self.validate_commitment()?; @@ -626,7 +637,10 @@ impl DeviceMemory { .memory_types[self.memory_type_index as usize]; // VUID-vkGetDeviceMemoryCommitment-memory-00690 - if !memory_type.property_flags.lazily_allocated { + if !memory_type + .property_flags + .intersects(MemoryPropertyFlags::LAZILY_ALLOCATED) + { return Err(DeviceMemoryError::NotLazilyAllocated); } @@ -855,212 +869,87 @@ pub enum MemoryImportInfo { }, } -vulkan_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. +vulkan_bitflags_enum! { #[non_exhaustive] - ExternalMemoryHandleType = ExternalMemoryHandleTypeFlags(u32); - // TODO: document - OpaqueFd = OPAQUE_FD, + /// A set of [`ExternalMemoryHandleType`] values. + ExternalMemoryHandleTypes, - // TODO: document - OpaqueWin32 = OPAQUE_WIN32, + /// A handle type used to export or import memory to/from an external source. + ExternalMemoryHandleType, - // TODO: document - OpaqueWin32Kmt = OPAQUE_WIN32_KMT, + = ExternalMemoryHandleTypeFlags(u32); - // TODO: document - D3D11Texture = D3D11_TEXTURE, + /// A POSIX file descriptor handle that is only usable with Vulkan and compatible APIs. + OPAQUE_FD, OpaqueFd = OPAQUE_FD, - // TODO: document - D3D11TextureKmt = D3D11_TEXTURE_KMT, + /// A Windows NT handle that is only usable with Vulkan and compatible APIs. + OPAQUE_WIN32, OpaqueWin32 = OPAQUE_WIN32, - // TODO: document - D3D12Heap = D3D12_HEAP, + /// A Windows global share handle that is only usable with Vulkan and compatible APIs. + OPAQUE_WIN32_KMT, OpaqueWin32Kmt = OPAQUE_WIN32_KMT, - // TODO: document - D3D12Resource = D3D12_RESOURCE, + /// A Windows NT handle that refers to a Direct3D 10 or 11 texture resource. + D3D11_TEXTURE, D3D11Texture = D3D11_TEXTURE, - // TODO: document - DmaBuf = DMA_BUF_EXT { + /// A Windows global share handle that refers to a Direct3D 10 or 11 texture resource. + 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], }, - // TODO: document - AndroidHardwareBuffer = ANDROID_HARDWARE_BUFFER_ANDROID { + /// A handle for an Android `AHardwareBuffer` object. + ANDROID_HARDWARE_BUFFER, AndroidHardwareBuffer = ANDROID_HARDWARE_BUFFER_ANDROID { device_extensions: [android_external_memory_android_hardware_buffer], }, - // TODO: document - HostAllocation = HOST_ALLOCATION_EXT { + /// A pointer to memory that was allocated by the host. + HOST_ALLOCATION, HostAllocation = HOST_ALLOCATION_EXT { device_extensions: [ext_external_memory_host], }, - // TODO: document - HostMappedForeignMemory = HOST_MAPPED_FOREIGN_MEMORY_EXT { + /// A pointer to a memory mapping on the host that maps non-host memory. + HOST_MAPPED_FOREIGN_MEMORY, HostMappedForeignMemory = HOST_MAPPED_FOREIGN_MEMORY_EXT { device_extensions: [ext_external_memory_host], }, - // TODO: document - ZirconVmo = ZIRCON_VMO_FUCHSIA { + /// A Zircon handle to a virtual memory object. + ZIRCON_VMO, ZirconVmo = ZIRCON_VMO_FUCHSIA { device_extensions: [fuchsia_external_memory], }, - // TODO: document - RdmaAddress = RDMA_ADDRESS_NV { + /// A Remote Direct Memory Address handle to an allocation that is accessible by remote devices. + RDMA_ADDRESS, RdmaAddress = RDMA_ADDRESS_NV { device_extensions: [nv_external_memory_rdma], }, } vulkan_bitflags! { - /// A mask of multiple handle types. #[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 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 { - 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. - #[non_exhaustive] MemoryAllocateFlags = MemoryAllocateFlags(u32); // TODO: implement // device_mask = DEVICE_MASK, /// 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 /// 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 /// [`ext_buffer_device_address`]: crate::device::DeviceExtensions::ext_buffer_device_address - device_address = DEVICE_ADDRESS, + DEVICE_ADDRESS = DEVICE_ADDRESS, // TODO: implement // device_address_capture_replay = DEVICE_ADDRESS_CAPTURE_REPLAY, @@ -1119,8 +1008,10 @@ pub enum DeviceMemoryError { memory_type_count: u32, }, - /// The memory type from which this memory was allocated does not have the - /// [`lazily_allocated`](crate::memory::MemoryPropertyFlags::lazily_allocated) flag set. + /// The memory type from which this memory was allocated does not have the [`LAZILY_ALLOCATED`] + /// flag set. + /// + /// [`LAZILY_ALLOCATED`]: crate::memory::MemoryPropertyFlags::LAZILY_ALLOCATED NotLazilyAllocated, /// Spec violation, containing the Valid Usage ID (VUID) from the Vulkan spec. @@ -1259,7 +1150,7 @@ impl From for DeviceMemoryError { /// # Examples /// /// ``` -/// use vulkano::memory::{DeviceMemory, MappedDeviceMemory, MemoryAllocateInfo}; +/// use vulkano::memory::{DeviceMemory, MappedDeviceMemory, MemoryAllocateInfo, MemoryPropertyFlags}; /// /// # let device: std::sync::Arc = return; /// // The memory type must be mappable. @@ -1268,7 +1159,7 @@ impl From for DeviceMemoryError { /// .memory_properties() /// .memory_types /// .iter() -/// .position(|t| t.property_flags.host_visible) +/// .position(|t| t.property_flags.intersects(MemoryPropertyFlags::HOST_VISIBLE)) /// .map(|i| i as u32) /// .unwrap(); // Vk specs guarantee that this can't fail /// @@ -1342,11 +1233,16 @@ impl MappedDeviceMemory { [memory.memory_type_index() as usize]; // VUID-vkMapMemory-memory-00682 - if !memory_type.property_flags.host_visible { + if !memory_type + .property_flags + .intersects(MemoryPropertyFlags::HOST_VISIBLE) + { 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; // Not required for merely mapping, but without this check the user can end up with @@ -1687,7 +1583,7 @@ impl From for MemoryMapError { mod tests { use super::MemoryAllocateInfo; use crate::{ - memory::{DeviceMemory, DeviceMemoryError}, + memory::{DeviceMemory, DeviceMemoryError, MemoryPropertyFlags}, OomError, }; @@ -1731,7 +1627,11 @@ mod tests { .memory_types .iter() .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(); match DeviceMemory::allocate( @@ -1757,7 +1657,11 @@ mod tests { .memory_types .iter() .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(); let heap_size = device.physical_device().memory_properties().memory_heaps [memory_type.heap_index as usize] diff --git a/vulkano/src/memory/mod.rs b/vulkano/src/memory/mod.rs index 59a9e2cb..65407331 100644 --- a/vulkano/src/memory/mod.rs +++ b/vulkano/src/memory/mod.rs @@ -40,8 +40,7 @@ //! # let physical_device: vulkano::device::physical::PhysicalDevice = return; //! for ty in physical_device.memory_properties().memory_types.iter() { //! println!("Memory type belongs to heap #{:?}", ty.heap_index); -//! println!("Host-accessible: {:?}", ty.property_flags.host_visible); -//! println!("Device-local: {:?}", ty.property_flags.device_local); +//! println!("Property flags: {:?}", ty.property_flags); //! } //! ``` //! @@ -153,12 +152,13 @@ pub struct MemoryType { } vulkan_bitflags! { - /// Properties of a memory type. #[non_exhaustive] + + /// Properties of a memory type. MemoryPropertyFlags = MemoryPropertyFlags(u32); /// 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 /// 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. /// /// 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, - /// device-local memory is preferred for host-to-device data transfer, while non-device-local - /// memory is preferred for device-to-host data transfer. This is because data is usually - /// written only once but potentially read several times, and because reads can take advantage - /// of caching while writes cannot. + /// at the destination of the transfer. Thus, if [`HOST_VISIBLE`] versions of both are + /// available, device-local memory is preferred for host-to-device data transfer, while + /// non-device-local memory is preferred for device-to-host data transfer. This is because data + /// is usually written only once but potentially read several times, and because reads can take + /// advantage of caching while writes cannot. /// - /// Devices may have memory types that are neither `device_local` nor `host_visible`. This 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 - /// `host_visible` memory. It can be used as overflow space if the device is out of memory. - device_local = DEVICE_LOCAL, + /// Devices may have memory types that are neither `DEVICE_LOCAL` nor [`HOST_VISIBLE`]. This + /// 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 + /// [`HOST_VISIBLE`] memory. It can be used as overflow space if the device is out of memory. + /// + /// [`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. /// /// 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 - /// 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 - /// can be both. - host_visible = HOST_VISIBLE, + /// `HOST_VISIBLE` memory is always at least either [`HOST_COHERENT`] or [`HOST_CACHED`], + /// but it can be both. + /// + /// [`HOST_COHERENT`]: MemoryPropertyFlags::HOST_COHERENT + /// [`HOST_CACHED`]: MemoryPropertyFlags::HOST_CACHED + HOST_VISIBLE = HOST_VISIBLE, - /// Host access to the memory does not require calling - /// [`invalidate_range`](MappedDeviceMemory::invalidate_range) to make device writes visible to - /// the host, nor [`flush_range`](MappedDeviceMemory::flush_range) to flush host writes back - /// to the device. - host_coherent = HOST_COHERENT, + /// Host access to the memory does not require calling [`invalidate_range`] to make device + /// writes visible to the host, nor [`flush_range`] to flush host writes back to the device. + /// + /// [`invalidate_range`]: MappedDeviceMemory::invalidate_range + /// [`flush_range`]: MappedDeviceMemory::flush_range + HOST_COHERENT = HOST_COHERENT, /// The memory is cached by the host. /// - /// `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 + /// `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 /// 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_cached = HOST_CACHED, + /// + /// [`HOST_VISIBLE`]: MemoryPropertyFlags::HOST_VISIBLE + HOST_CACHED = HOST_CACHED, /// Allocations made from the memory are lazy. /// @@ -218,13 +227,19 @@ vulkan_bitflags! { /// allocation. /// /// Memory of this type can only be used on images created with a certain flag, and is never - /// `host_visible`. - lazily_allocated = LAZILY_ALLOCATED, + /// [`HOST_VISIBLE`]. + /// + /// [`HOST_VISIBLE`]: MemoryPropertyFlags::HOST_VISIBLE + LAZILY_ALLOCATED = LAZILY_ALLOCATED, /// 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`. - protected = PROTECTED { + /// Memory of this type is never [`HOST_VISIBLE`], [`HOST_COHERENT`] or [`HOST_CACHED`]. + /// + /// [`HOST_VISIBLE`]: MemoryPropertyFlags::HOST_VISIBLE + /// [`HOST_COHERENT`]: MemoryPropertyFlags::HOST_COHERENT + /// [`HOST_CACHED`]: MemoryPropertyFlags::HOST_CACHED + PROTECTED = PROTECTED { 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 /// 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], }, /// The memory is not cached on the device. /// - /// `device_uncached` memory is always also `device_coherent`. - device_uncached = DEVICE_UNCACHED_AMD { + /// `DEVICE_UNCACHED` memory is always also [`DEVICE_COHERENT`]. + /// + /// [`DEVICE_COHERENT`]: MemoryPropertyFlags::DEVICE_COHERENT + DEVICE_UNCACHED = DEVICE_UNCACHED_AMD { device_extensions: [amd_device_coherent_memory], }, /// 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], }, } @@ -262,16 +279,17 @@ pub struct MemoryHeap { } vulkan_bitflags! { - /// Attributes of a memory heap. #[non_exhaustive] + + /// Attributes of a memory heap. MemoryHeapFlags = MemoryHeapFlags(u32); /// 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 /// replicated across each physical device's instance of this heap. - multi_instance = MULTI_INSTANCE { + MULTI_INSTANCE = MULTI_INSTANCE { api_version: V1_1, instance_extensions: [khr_device_group_creation], }, diff --git a/vulkano/src/pipeline/compute.rs b/vulkano/src/pipeline/compute.rs index 4cd3aa9a..39dba97c 100644 --- a/vulkano/src/pipeline/compute.rs +++ b/vulkano/src/pipeline/compute.rs @@ -491,10 +491,7 @@ mod tests { let memory_allocator = StandardMemoryAllocator::new_default(device.clone()); let data_buffer = CpuAccessibleBuffer::from_data( &memory_allocator, - BufferUsage { - storage_buffer: true, - ..BufferUsage::empty() - }, + BufferUsage::STORAGE_BUFFER, false, 0, ) diff --git a/vulkano/src/pipeline/graphics/builder.rs b/vulkano/src/pipeline/graphics/builder.rs index 6e07cc30..c628c1f0 100644 --- a/vulkano/src/pipeline/graphics/builder.rs +++ b/vulkano/src/pipeline/graphics/builder.rs @@ -34,7 +34,8 @@ use super::{ use crate::{ descriptor_set::layout::{DescriptorSetLayout, DescriptorSetLayoutCreateInfo}, device::{Device, DeviceOwned}, - format::NumericType, + format::{FormatFeatures, NumericType}, + image::ImageAspects, pipeline::{ cache::PipelineCache, graphics::{ @@ -484,7 +485,8 @@ where // VUID-VkGraphicsPipelineCreateInfo-multiview-06577 if view_mask != 0 && !device.enabled_features().multiview { 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 { features: &["multiview"], ..Default::default() @@ -519,7 +521,7 @@ where // Use unchecked, because all validation has been done above. if !unsafe { physical_device.format_properties_unchecked(format) } .potential_format_features() - .color_attachment + .intersects(FormatFeatures::COLOR_ATTACHMENT) { return Err( GraphicsPipelineCreationError::ColorAttachmentFormatUsageNotSupported { @@ -537,7 +539,7 @@ where // Use unchecked, because all validation has been done above. if !unsafe { physical_device.format_properties_unchecked(format) } .potential_format_features() - .depth_stencil_attachment + .intersects(FormatFeatures::DEPTH_STENCIL_ATTACHMENT) { return Err( GraphicsPipelineCreationError::DepthAttachmentFormatUsageNotSupported, @@ -545,7 +547,7 @@ where } // VUID-VkGraphicsPipelineCreateInfo-renderPass-06587 - if !format.aspects().depth { + if !format.aspects().intersects(ImageAspects::DEPTH) { return Err( GraphicsPipelineCreationError::DepthAttachmentFormatUsageNotSupported, ); @@ -560,7 +562,7 @@ where // Use unchecked, because all validation has been done above. if !unsafe { physical_device.format_properties_unchecked(format) } .potential_format_features() - .depth_stencil_attachment + .intersects(FormatFeatures::DEPTH_STENCIL_ATTACHMENT) { return Err( GraphicsPipelineCreationError::StencilAttachmentFormatUsageNotSupported, @@ -568,7 +570,7 @@ where } // VUID-VkGraphicsPipelineCreateInfo-renderPass-06588 - if !format.aspects().stencil { + if !format.aspects().intersects(ImageAspects::STENCIL) { return Err( GraphicsPipelineCreationError::StencilAttachmentFormatUsageNotSupported, ); @@ -663,7 +665,9 @@ where .vertex_attribute_instance_rate_divisor { 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 { features: &["vertex_attribute_instance_rate_divisor"], ..Default::default() @@ -678,7 +682,9 @@ where .vertex_attribute_instance_rate_zero_divisor { 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 { features: &["vertex_attribute_instance_rate_zero_divisor"], ..Default::default() @@ -754,7 +760,7 @@ where }; // VUID-VkVertexInputAttributeDescription-format-00623 - if !format_features.vertex_buffer { + if !format_features.intersects(FormatFeatures::VERTEX_BUFFER) { return Err( GraphicsPipelineCreationError::VertexInputAttributeUnsupportedFormat { location, @@ -805,9 +811,8 @@ where && !device.enabled_features().triangle_fans { return Err(GraphicsPipelineCreationError::RequirementNotMet { - required_for: - "this device is a portability subset device, and \ - `input_assembly_state.topology` is \ + required_for: "this device is a portability subset \ + device, and `input_assembly_state.topology` is \ `StateMode::Fixed(PrimitiveTopology::TriangleFan)`", requires_one_of: RequiresOneOf { features: &["triangle_fans"], @@ -823,7 +828,8 @@ where // VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00429 if !device.enabled_features().geometry_shader { 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 { features: &["geometry_shader"], ..Default::default() @@ -835,7 +841,8 @@ where // VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00430 if !device.enabled_features().tessellation_shader { 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 { features: &["tessellation_shader"], ..Default::default() @@ -858,8 +865,8 @@ where || device.enabled_features().extended_dynamic_state) { return Err(GraphicsPipelineCreationError::RequirementNotMet { - required_for: - "`input_assembly_state.topology` is `PartialStateMode::Dynamic`", + required_for: "`input_assembly_state.topology` is \ + `PartialStateMode::Dynamic`", requires_one_of: RequiresOneOf { api_version: Some(Version::V1_3), features: &["extended_dynamic_state"], @@ -884,7 +891,10 @@ where // VUID-VkPipelineInputAssemblyStateCreateInfo-topology-06252 if !device.enabled_features().primitive_topology_list_restart { 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 { features: &["primitive_topology_list_restart"], ..Default::default() @@ -899,7 +909,10 @@ where .primitive_topology_patch_list_restart { 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 { features: &["primitive_topology_patch_list_restart"], ..Default::default() @@ -917,7 +930,8 @@ where || device.enabled_features().extended_dynamic_state2) { 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 { api_version: Some(Version::V1_3), features: &["extended_dynamic_state2"], @@ -1089,7 +1103,8 @@ where // VUID-VkGraphicsPipelineCreateInfo-renderPass-06057 if view_mask != 0 { 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 { features: &["multiview_tessellation_shader"], ..Default::default() @@ -1158,7 +1173,8 @@ where // VUID-VkGraphicsPipelineCreateInfo-renderPass-06058 if view_mask != 0 { 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 { features: &["multiview_geometry_shader"], ..Default::default() @@ -1209,7 +1225,8 @@ where || device.enabled_features().extended_dynamic_state2) { 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 { api_version: Some(Version::V1_3), features: &["extended_dynamic_state"], @@ -1244,8 +1261,8 @@ where && !device.enabled_features().fill_mode_non_solid { return Err(GraphicsPipelineCreationError::RequirementNotMet { - required_for: - "`rasterization_state.polygon_mode` is not `PolygonMode::Fill`", + required_for: "`rasterization_state.polygon_mode` is not \ + `PolygonMode::Fill`", requires_one_of: RequiresOneOf { features: &["fill_mode_non_solid"], ..Default::default() @@ -1264,8 +1281,8 @@ where || device.enabled_features().extended_dynamic_state) { return Err(GraphicsPipelineCreationError::RequirementNotMet { - required_for: - "`rasterization_state.cull_mode` is `StateMode::Dynamic`", + required_for: "`rasterization_state.cull_mode` is \ + `StateMode::Dynamic`", requires_one_of: RequiresOneOf { api_version: Some(Version::V1_3), features: &["extended_dynamic_state"], @@ -1287,8 +1304,8 @@ where || device.enabled_features().extended_dynamic_state) { return Err(GraphicsPipelineCreationError::RequirementNotMet { - required_for: - "`rasterization_state.front_face` is `StateMode::Dynamic`", + required_for: "`rasterization_state.front_face` is \ + `StateMode::Dynamic`", requires_one_of: RequiresOneOf { api_version: Some(Version::V1_3), features: &["extended_dynamic_state"], @@ -1311,7 +1328,9 @@ where || device.enabled_features().extended_dynamic_state2) { 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 { api_version: Some(Version::V1_3), features: &["extended_dynamic_state2"], @@ -1325,7 +1344,9 @@ where && !device.enabled_features().depth_bias_clamp { 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 { features: &["depth_bias_clamp"], ..Default::default() @@ -1339,7 +1360,8 @@ where && !device.enabled_features().wide_lines { 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 { features: &["wide_lines"], ..Default::default() @@ -1357,7 +1379,8 @@ where // VUID-VkPipelineRasterizationLineStateCreateInfoEXT-lineRasterizationMode-02768 if !device.enabled_features().rectangular_lines { 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 { features: &["rectangular_lines"], ..Default::default() @@ -1369,7 +1392,8 @@ where // VUID-VkPipelineRasterizationLineStateCreateInfoEXT-lineRasterizationMode-02769 if !device.enabled_features().bresenham_lines { 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 { features: &["bresenham_lines"], ..Default::default() @@ -1381,7 +1405,8 @@ where // VUID-VkPipelineRasterizationLineStateCreateInfoEXT-lineRasterizationMode-02770 if !device.enabled_features().smooth_lines { 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 { features: &["smooth_lines"], ..Default::default() @@ -1397,7 +1422,10 @@ where // VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02774 if !device.enabled_features().stippled_rectangular_lines { 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 { features: &["stippled_rectangular_lines"], ..Default::default() @@ -1416,7 +1444,10 @@ where // VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02771 if !device.enabled_features().stippled_rectangular_lines { 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 { features: &["stippled_rectangular_lines"], ..Default::default() @@ -1428,7 +1459,10 @@ where // VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02772 if !device.enabled_features().stippled_bresenham_lines { 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 { features: &["stippled_bresenham_lines"], ..Default::default() @@ -1440,7 +1474,10 @@ where // VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02773 if !device.enabled_features().stippled_smooth_lines { 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 { features: &["stippled_smooth_lines"], ..Default::default() @@ -1459,7 +1496,8 @@ where } else { if line_rasterization_mode != LineRasterizationMode::Default { 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 { device_extensions: &["ext_line_rasterization"], ..Default::default() @@ -1509,7 +1547,8 @@ where if error { 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 { device_extensions: &["ext_discard_rectangles"], ..Default::default() @@ -1559,8 +1598,8 @@ where .extended_dynamic_state2_patch_control_points { return Err(GraphicsPipelineCreationError::RequirementNotMet { - required_for: - "`tessellation_state.patch_control_points` is `StateMode::Dynamic`", + required_for: "`tessellation_state.patch_control_points` is \ + `StateMode::Dynamic`", requires_one_of: RequiresOneOf { features: &["extended_dynamic_state2_patch_control_points"], ..Default::default() @@ -1637,7 +1676,9 @@ where || device.enabled_features().extended_dynamic_state) { 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 { api_version: Some(Version::V1_3), features: &["extended_dynamic_state"], @@ -1669,7 +1710,9 @@ where || device.enabled_features().extended_dynamic_state) { 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 { api_version: Some(Version::V1_3), features: &["extended_dynamic_state"], @@ -1707,7 +1750,9 @@ where || device.enabled_features().extended_dynamic_state) { 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 { api_version: Some(Version::V1_3), features: &["extended_dynamic_state"], @@ -1728,7 +1773,9 @@ where || device.enabled_features().extended_dynamic_state) { 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 { api_version: Some(Version::V1_3), features: &["extended_dynamic_state"], @@ -1756,7 +1803,8 @@ where // VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217 if viewport_scissor_count > 1 && !device.enabled_features().multi_viewport { 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 { features: &["multi_viewport"], ..Default::default() @@ -1867,8 +1915,8 @@ where || device.enabled_features().extended_dynamic_state) { return Err(GraphicsPipelineCreationError::RequirementNotMet { - required_for: - "`depth_stencil_state.depth` is `Some(depth_state)`, where `depth_state.enable_dynamic` is set", + required_for: "`depth_stencil_state.depth` is `Some(depth_state)`, where \ + `depth_state.enable_dynamic` is set", requires_one_of: RequiresOneOf { api_version: Some(Version::V1_3), features: &["extended_dynamic_state"], @@ -1897,7 +1945,9 @@ where || device.enabled_features().extended_dynamic_state) { 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 { api_version: Some(Version::V1_3), features: &["extended_dynamic_state"], @@ -1919,7 +1969,9 @@ where || device.enabled_features().extended_dynamic_state) { 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 { api_version: Some(Version::V1_3), features: &["extended_dynamic_state"], @@ -1954,7 +2006,9 @@ where || device.enabled_features().extended_dynamic_state) { 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 { api_version: Some(Version::V1_3), features: &["extended_dynamic_state"], @@ -1970,7 +2024,9 @@ where && !(0.0..1.0).contains(bounds.end()) { 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 { device_extensions: &["ext_depth_range_unrestricted"], ..Default::default() @@ -2004,8 +2060,8 @@ where || device.enabled_features().extended_dynamic_state) { return Err(GraphicsPipelineCreationError::RequirementNotMet { - required_for: - "`depth_stencil_state.stencil` is `Some(stencil_state)`, where `stencil_state.enable_dynamic` is set", + required_for: "`depth_stencil_state.stencil` is `Some(stencil_state)`, \ + where `stencil_state.enable_dynamic` is set", requires_one_of: RequiresOneOf { api_version: Some(Version::V1_3), features: &["extended_dynamic_state"], @@ -2043,7 +2099,9 @@ where || device.enabled_features().extended_dynamic_state) { 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 { api_version: Some(Version::V1_3), features: &["extended_dynamic_state"], @@ -2209,8 +2267,8 @@ where // VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04869 if !device.enabled_features().extended_dynamic_state2_logic_op { return Err(GraphicsPipelineCreationError::RequirementNotMet { - required_for: - "`color_blend_state.logic_op` is `Some(StateMode::Dynamic)`", + required_for: "`color_blend_state.logic_op` is \ + `Some(StateMode::Dynamic)`", requires_one_of: RequiresOneOf { features: &["extended_dynamic_state2_logic_op"], ..Default::default() @@ -2247,7 +2305,8 @@ where // VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605 if !iter.all(|state| state == first) { 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 { features: &["independent_blend"], ..Default::default() @@ -2312,9 +2371,9 @@ where { return Err(GraphicsPipelineCreationError::RequirementNotMet { required_for: "`color_blend_state.attachments` has an element where \ - `blend` is `Some(blend)`, where `blend.color_source`, \ - `blend.color_destination`, `blend.alpha_source` or \ - `blend.alpha_destination` is `BlendFactor::Src1*`", + `blend` is `Some(blend)`, where `blend.color_source`, \ + `blend.color_destination`, `blend.alpha_source` or \ + `blend.alpha_destination` is `BlendFactor::Src1*`", requires_one_of: RequiresOneOf { features: &["dual_src_blend"], ..Default::default() @@ -2344,7 +2403,7 @@ where physical_device .format_properties_unchecked(format) .potential_format_features() - .color_attachment_blend + .intersects(FormatFeatures::COLOR_ATTACHMENT_BLEND) }) { return Err( GraphicsPipelineCreationError::ColorAttachmentFormatBlendNotSupported { @@ -2385,7 +2444,8 @@ where // VUID-VkPipelineColorWriteCreateInfoEXT-pAttachments-04801 if !enable && !device.enabled_features().color_write_enable { 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 { features: &["color_write_enable"], ..Default::default() @@ -2397,7 +2457,8 @@ where // VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04800 if !device.enabled_features().color_write_enable { 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 { features: &["color_write_enable"], ..Default::default() diff --git a/vulkano/src/pipeline/graphics/color_blend.rs b/vulkano/src/pipeline/graphics/color_blend.rs index 99eeb124..40b5ccef 100644 --- a/vulkano/src/pipeline/graphics/color_blend.rs +++ b/vulkano/src/pipeline/graphics/color_blend.rs @@ -144,6 +144,7 @@ impl Default for ColorBlendState { } vulkan_enum! { + #[non_exhaustive] /// Which logical operation to apply to the output values. /// /// 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. /// /// Also note that some implementations don't support logic operations. - #[non_exhaustive] LogicOp = LogicOp(i32); /// Returns `0`. @@ -318,6 +318,8 @@ impl From for ash::vk::PipelineColorBlendAttachmentState { } vulkan_enum! { + #[non_exhaustive] + /// The operation that takes `source` (output from the fragment shader), `destination` (value /// currently in the framebuffer attachment) and `blend_constant` input values, /// 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 /// [`dual_src_blend`](crate::device::Features::dual_src_blend) feature must be enabled on the /// device when these are used. - #[non_exhaustive] BlendFactor = BlendFactor(i32); /// Always `0`. @@ -400,9 +401,10 @@ vulkan_enum! { } vulkan_enum! { + #[non_exhaustive] + /// The arithmetic operation that is applied between the `source` and `destination` component /// values, after the appropriate `BlendFactor` is applied to both. - #[non_exhaustive] BlendOp = BlendOp(i32); /// `source + destination`. @@ -658,14 +660,14 @@ vulkan_bitflags! { ColorComponents = ColorComponentFlags(u32); /// The red component. - r = R, + R = R, /// The green component. - g = G, + G = G, /// The blue component. - b = B, + B = B, /// The alpha component. - a = A, + A = A, } diff --git a/vulkano/src/pipeline/graphics/depth_stencil.rs b/vulkano/src/pipeline/graphics/depth_stencil.rs index 480b25a5..650be60e 100644 --- a/vulkano/src/pipeline/graphics/depth_stencil.rs +++ b/vulkano/src/pipeline/graphics/depth_stencil.rs @@ -251,8 +251,9 @@ impl Default for StencilOps { } vulkan_enum! { - /// Operation to perform after the depth and stencil tests. #[non_exhaustive] + + /// Operation to perform after the depth and stencil tests. StencilOp = StencilOp(i32); // TODO: document @@ -281,8 +282,9 @@ vulkan_enum! { } vulkan_enum! { - /// Specifies a face for stencil operations. #[non_exhaustive] + + /// Specifies a face for stencil operations. StencilFaces = StencilFaceFlags(u32); // TODO: document @@ -303,10 +305,11 @@ pub struct DynamicStencilValue { } vulkan_enum! { + #[non_exhaustive] + /// Specifies how two values should be compared to decide whether a test passes or fails. /// /// Used for both depth testing and stencil testing. - #[non_exhaustive] CompareOp = CompareOp(i32); /// The test never passes. diff --git a/vulkano/src/pipeline/graphics/discard_rectangle.rs b/vulkano/src/pipeline/graphics/discard_rectangle.rs index 2aeaf6c5..3548870f 100644 --- a/vulkano/src/pipeline/graphics/discard_rectangle.rs +++ b/vulkano/src/pipeline/graphics/discard_rectangle.rs @@ -51,8 +51,9 @@ impl Default for DiscardRectangleState { } vulkan_enum! { - /// The mode in which the discard rectangle test operates. #[non_exhaustive] + + /// The mode in which the discard rectangle test operates. DiscardRectangleMode = DiscardRectangleModeEXT(i32); /// Samples that are inside a rectangle are kept, samples that are outside all rectangles diff --git a/vulkano/src/pipeline/graphics/input_assembly.rs b/vulkano/src/pipeline/graphics/input_assembly.rs index 7fb62526..2243243c 100644 --- a/vulkano/src/pipeline/graphics/input_assembly.rs +++ b/vulkano/src/pipeline/graphics/input_assembly.rs @@ -90,6 +90,8 @@ impl Default for InputAssemblyState { } vulkan_enum! { + #[non_exhaustive] + /// Describes how vertices must be grouped together to form primitives. /// /// When enabling primitive restart, "list" topologies require a feature to be enabled on the @@ -100,8 +102,26 @@ vulkan_enum! { /// - All other "list" topologies require the /// [`primitive_topology_list_restart`](crate::device::Features::primitive_topology_list_restart) /// feature. - #[non_exhaustive] - PrimitiveTopology = PrimitiveTopology(i32); + PrimitiveTopology impl { + /// Returns the topology class of this topology. + #[inline] + pub fn class(self) -> PrimitiveTopologyClass { + match self { + Self::PointList => PrimitiveTopologyClass::Point, + Self::LineList + | Self::LineStrip + | Self::LineListWithAdjacency + | Self::LineStripWithAdjacency => PrimitiveTopologyClass::Line, + Self::TriangleList + | Self::TriangleStrip + | Self::TriangleFan + | Self::TriangleListWithAdjacency + | Self::TriangleStripWithAdjacency => PrimitiveTopologyClass::Triangle, + Self::PatchList => PrimitiveTopologyClass::Patch, + } + } + } + = PrimitiveTopology(i32); /// A series of separate point primitives. PointList = POINT_LIST, @@ -156,26 +176,6 @@ impl Default for PrimitiveTopology { } } -impl PrimitiveTopology { - /// Returns the topology class of this topology. - #[inline] - pub fn class(&self) -> PrimitiveTopologyClass { - match self { - Self::PointList => PrimitiveTopologyClass::Point, - Self::LineList - | Self::LineStrip - | Self::LineListWithAdjacency - | Self::LineStripWithAdjacency => PrimitiveTopologyClass::Line, - Self::TriangleList - | Self::TriangleStrip - | Self::TriangleFan - | Self::TriangleListWithAdjacency - | Self::TriangleStripWithAdjacency => PrimitiveTopologyClass::Triangle, - Self::PatchList => PrimitiveTopologyClass::Patch, - } - } -} - /// Describes the shape of a primitive topology. #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum PrimitiveTopologyClass { @@ -187,7 +187,7 @@ pub enum PrimitiveTopologyClass { impl PrimitiveTopologyClass { /// Returns a representative example of this topology class. - pub(crate) fn example(&self) -> PrimitiveTopology { + pub(crate) fn example(self) -> PrimitiveTopology { match self { Self::Point => PrimitiveTopology::PointList, Self::Line => PrimitiveTopology::LineList, @@ -225,8 +225,9 @@ unsafe impl Index for u32 { } vulkan_enum! { - /// An enumeration of all valid index types. #[non_exhaustive] + + /// An enumeration of all valid index types. IndexType = IndexType(i32); // TODO: document @@ -251,7 +252,7 @@ vulkan_enum! { impl IndexType { /// Returns the size in bytes of indices of this type. #[inline] - pub fn size(&self) -> DeviceSize { + pub fn size(self) -> DeviceSize { match self { IndexType::U8 => 1, IndexType::U16 => 2, diff --git a/vulkano/src/pipeline/graphics/rasterization.rs b/vulkano/src/pipeline/graphics/rasterization.rs index d66c80c4..062635ff 100644 --- a/vulkano/src/pipeline/graphics/rasterization.rs +++ b/vulkano/src/pipeline/graphics/rasterization.rs @@ -176,13 +176,14 @@ pub struct DepthBias { } vulkan_enum! { + #[non_exhaustive] + /// Specifies the culling mode. /// /// This setting works in pair with `front_face`. The `front_face` setting tells the GPU whether /// clockwise or counter-clockwise correspond to the front and the back of each triangle. Then /// `cull_mode` lets you specify whether front faces should be discarded, back faces should be /// discarded, or none, or both. - #[non_exhaustive] CullMode = CullModeFlags(u32); /// No culling. @@ -207,8 +208,9 @@ impl Default for CullMode { } vulkan_enum! { - /// Specifies which triangle orientation corresponds to the front or the triangle. #[non_exhaustive] + + /// Specifies which triangle orientation corresponds to the front or the triangle. FrontFace = FrontFace(i32); /// Triangles whose vertices are oriented counter-clockwise on the screen will be considered @@ -229,8 +231,9 @@ impl Default for FrontFace { } vulkan_enum! { - // TODO: document #[non_exhaustive] + + // TODO: document PolygonMode = PolygonMode(i32); // TODO: document @@ -262,8 +265,9 @@ impl Default for PolygonMode { } vulkan_enum! { - /// The rasterization mode to use for lines. #[non_exhaustive] + + /// The rasterization mode to use for lines. LineRasterizationMode = LineRasterizationModeEXT(i32); /// If the [`strict_lines`](crate::device::Properties::strict_lines) device property is `true`, diff --git a/vulkano/src/pipeline/graphics/vertex_input/vertex.rs b/vulkano/src/pipeline/graphics/vertex_input/vertex.rs index 11e3c50e..71a2e12d 100644 --- a/vulkano/src/pipeline/graphics/vertex_input/vertex.rs +++ b/vulkano/src/pipeline/graphics/vertex_input/vertex.rs @@ -54,9 +54,9 @@ pub enum VertexMemberTy { impl VertexMemberTy { /// Returns true if a combination of `(type, array_size)` matches a format. #[inline] - pub fn matches(&self, array_size: usize, format: Format, num_locs: u32) -> bool { + pub fn matches(self, array_size: usize, format: Format, num_locs: u32) -> bool { // TODO: implement correctly - let my_size = match *self { + let my_size = match self { VertexMemberTy::I8 => 1, VertexMemberTy::U8 => 1, VertexMemberTy::I16 => 2, diff --git a/vulkano/src/pipeline/layout.rs b/vulkano/src/pipeline/layout.rs index 289d16c9..4ed761be 100644 --- a/vulkano/src/pipeline/layout.rs +++ b/vulkano/src/pipeline/layout.rs @@ -227,49 +227,48 @@ impl PipelineLayout { } for layout_binding in set_layout.bindings().values() { - num_resources - .increment(layout_binding.descriptor_count, &layout_binding.stages); + num_resources.increment(layout_binding.descriptor_count, layout_binding.stages); match layout_binding.descriptor_type { DescriptorType::Sampler => { num_samplers - .increment(layout_binding.descriptor_count, &layout_binding.stages); + .increment(layout_binding.descriptor_count, layout_binding.stages); } DescriptorType::CombinedImageSampler => { num_samplers - .increment(layout_binding.descriptor_count, &layout_binding.stages); + .increment(layout_binding.descriptor_count, layout_binding.stages); num_sampled_images - .increment(layout_binding.descriptor_count, &layout_binding.stages); + .increment(layout_binding.descriptor_count, layout_binding.stages); } DescriptorType::SampledImage | DescriptorType::UniformTexelBuffer => { num_sampled_images - .increment(layout_binding.descriptor_count, &layout_binding.stages); + .increment(layout_binding.descriptor_count, layout_binding.stages); } DescriptorType::StorageImage | DescriptorType::StorageTexelBuffer => { num_storage_images - .increment(layout_binding.descriptor_count, &layout_binding.stages); + .increment(layout_binding.descriptor_count, layout_binding.stages); } DescriptorType::UniformBuffer => { num_uniform_buffers - .increment(layout_binding.descriptor_count, &layout_binding.stages); + .increment(layout_binding.descriptor_count, layout_binding.stages); } DescriptorType::UniformBufferDynamic => { num_uniform_buffers - .increment(layout_binding.descriptor_count, &layout_binding.stages); + .increment(layout_binding.descriptor_count, layout_binding.stages); num_uniform_buffers_dynamic += 1; } DescriptorType::StorageBuffer => { num_storage_buffers - .increment(layout_binding.descriptor_count, &layout_binding.stages); + .increment(layout_binding.descriptor_count, layout_binding.stages); } DescriptorType::StorageBufferDynamic => { num_storage_buffers - .increment(layout_binding.descriptor_count, &layout_binding.stages); + .increment(layout_binding.descriptor_count, layout_binding.stages); num_storage_buffers_dynamic += 1; } DescriptorType::InputAttachment => { num_input_attachments - .increment(layout_binding.descriptor_count, &layout_binding.stages); + .increment(layout_binding.descriptor_count, layout_binding.stages); } } } @@ -651,7 +650,7 @@ impl PipelineLayout { // FIXME: check push constants if let Some(range) = push_constant_range { for own_range in self.push_constant_ranges.iter() { - if range.stages.intersects(&own_range.stages) && // check if it shares any stages + if range.stages.intersects(own_range.stages) && // check if it shares any stages (range.offset < own_range.offset || // our range must start before and end after the given range own_range.offset + own_range.size < range.offset + range.size) { @@ -1183,24 +1182,24 @@ struct Counter { } impl Counter { - fn increment(&mut self, num: u32, stages: &ShaderStages) { + fn increment(&mut self, num: u32, stages: ShaderStages) { self.total += num; - if stages.compute { + if stages.intersects(ShaderStages::COMPUTE) { self.compute += num; } - if stages.vertex { + if stages.intersects(ShaderStages::VERTEX) { self.vertex += num; } - if stages.tessellation_control { + if stages.intersects(ShaderStages::TESSELLATION_CONTROL) { self.tess_ctl += num; } - if stages.tessellation_evaluation { + if stages.intersects(ShaderStages::TESSELLATION_EVALUATION) { self.tess_eval += num; } - if stages.geometry { + if stages.intersects(ShaderStages::GEOMETRY) { self.geometry += num; } - if stages.fragment { + if stages.intersects(ShaderStages::FRAGMENT) { self.frag += num; } } @@ -1242,37 +1241,24 @@ mod tests { ( &[ PushConstantRange { - stages: ShaderStages { - fragment: true, - ..Default::default() - }, + stages: ShaderStages::FRAGMENT, offset: 0, size: 12, }, PushConstantRange { - stages: ShaderStages { - vertex: true, - ..Default::default() - }, + stages: ShaderStages::VERTEX, offset: 0, size: 40, }, ][..], &[ PushConstantRange { - stages: ShaderStages { - vertex: true, - fragment: true, - ..Default::default() - }, + stages: ShaderStages::VERTEX | ShaderStages::FRAGMENT, offset: 0, size: 12, }, PushConstantRange { - stages: ShaderStages { - vertex: true, - ..Default::default() - }, + stages: ShaderStages::VERTEX, offset: 12, size: 28, }, @@ -1289,45 +1275,29 @@ mod tests { ( &[ PushConstantRange { - stages: ShaderStages { - fragment: true, - ..Default::default() - }, + stages: ShaderStages::FRAGMENT, offset: 0, size: 12, }, PushConstantRange { - stages: ShaderStages { - vertex: true, - ..Default::default() - }, + stages: ShaderStages::VERTEX, offset: 4, size: 36, }, ][..], &[ PushConstantRange { - stages: ShaderStages { - fragment: true, - ..Default::default() - }, + stages: ShaderStages::FRAGMENT, offset: 0, size: 4, }, PushConstantRange { - stages: ShaderStages { - fragment: true, - vertex: true, - ..Default::default() - }, + stages: ShaderStages::FRAGMENT | ShaderStages::VERTEX, offset: 4, size: 8, }, PushConstantRange { - stages: ShaderStages { - vertex: true, - ..Default::default() - }, + stages: ShaderStages::VERTEX, offset: 12, size: 28, }, @@ -1348,91 +1318,59 @@ mod tests { ( &[ PushConstantRange { - stages: ShaderStages { - fragment: true, - ..Default::default() - }, + stages: ShaderStages::FRAGMENT, offset: 0, size: 12, }, PushConstantRange { - stages: ShaderStages { - compute: true, - ..Default::default() - }, + stages: ShaderStages::COMPUTE, offset: 8, size: 12, }, PushConstantRange { - stages: ShaderStages { - vertex: true, - ..Default::default() - }, + stages: ShaderStages::VERTEX, offset: 4, size: 12, }, PushConstantRange { - stages: ShaderStages { - tessellation_control: true, - ..Default::default() - }, + stages: ShaderStages::TESSELLATION_CONTROL, offset: 8, size: 24, }, ][..], &[ PushConstantRange { - stages: ShaderStages { - fragment: true, - ..Default::default() - }, + stages: ShaderStages::FRAGMENT, offset: 0, size: 4, }, PushConstantRange { - stages: ShaderStages { - fragment: true, - vertex: true, - ..Default::default() - }, + stages: ShaderStages::FRAGMENT | ShaderStages::VERTEX, offset: 4, size: 4, }, PushConstantRange { - stages: ShaderStages { - vertex: true, - fragment: true, - compute: true, - tessellation_control: true, - ..Default::default() - }, + stages: ShaderStages::VERTEX + | ShaderStages::FRAGMENT + | ShaderStages::COMPUTE + | ShaderStages::TESSELLATION_CONTROL, offset: 8, size: 4, }, PushConstantRange { - stages: ShaderStages { - vertex: true, - compute: true, - tessellation_control: true, - ..Default::default() - }, + stages: ShaderStages::VERTEX + | ShaderStages::COMPUTE + | ShaderStages::TESSELLATION_CONTROL, offset: 12, size: 4, }, PushConstantRange { - stages: ShaderStages { - compute: true, - tessellation_control: true, - ..Default::default() - }, + stages: ShaderStages::COMPUTE | ShaderStages::TESSELLATION_CONTROL, offset: 16, size: 4, }, PushConstantRange { - stages: ShaderStages { - tessellation_control: true, - ..Default::default() - }, + stages: ShaderStages::TESSELLATION_CONTROL, offset: 20, size: 12, }, diff --git a/vulkano/src/pipeline/mod.rs b/vulkano/src/pipeline/mod.rs index c35f5dae..45b6fb79 100644 --- a/vulkano/src/pipeline/mod.rs +++ b/vulkano/src/pipeline/mod.rs @@ -40,13 +40,14 @@ pub trait Pipeline: DeviceOwned { } vulkan_enum! { + #[non_exhaustive] + /// The type of a pipeline. /// /// When binding a pipeline or descriptor sets in a command buffer, the state for each bind point /// is independent from the others. This means that it is possible, for example, to bind a graphics /// pipeline without disturbing any bound compute pipeline. Likewise, binding descriptor sets for /// the `Compute` bind point does not affect sets that were bound to the `Graphics` bind point. - #[non_exhaustive] PipelineBindPoint = PipelineBindPoint(i32); // TODO: document @@ -69,9 +70,10 @@ vulkan_enum! { } vulkan_enum! { + #[non_exhaustive] + /// A particular state value within a graphics pipeline that can be dynamically set by a command /// buffer. - #[non_exhaustive] DynamicState = DynamicState(i32); // TODO: document diff --git a/vulkano/src/query.rs b/vulkano/src/query.rs index 895c80f1..c9f5ff12 100644 --- a/vulkano/src/query.rs +++ b/vulkano/src/query.rs @@ -328,15 +328,18 @@ impl<'a> QueriesRange<'a> { /// Copies the results of this range of queries to a buffer on the CPU. /// - /// [`self.pool().ty().result_len()`](QueryType::result_len) elements - /// will be written for each query in the range, plus 1 extra element per query if - /// [`QueryResultFlags::with_availability`] is enabled. - /// The provided buffer must be large enough to hold the data. + /// [`self.pool().ty().result_len()`] will be written for each query in the range, plus 1 extra + /// element per query if [`WITH_AVAILABILITY`] is enabled. The provided buffer must be large + /// enough to hold the data. /// /// `true` is returned if every result was available and written to the buffer. `false` /// is returned if some results were not yet available; these will not be written to the buffer. /// - /// See also [`copy_query_pool_results`](crate::command_buffer::AutoCommandBufferBuilder::copy_query_pool_results). + /// See also [`copy_query_pool_results`]. + /// + /// [`self.pool().ty().result_len()`]: QueryType::result_len + /// [`WITH_AVAILABILITY`]: QueryResultFlags::WITH_AVAILABILITY + /// [`copy_query_pool_results`]: crate::command_buffer::AutoCommandBufferBuilder::copy_query_pool_results #[inline] pub fn get_results( &self, @@ -393,8 +396,8 @@ impl<'a> QueriesRange<'a> { debug_assert!(buffer_start % std::mem::size_of::() as DeviceSize == 0); let count = self.range.end - self.range.start; - let per_query_len = - self.pool.query_type.result_len() + flags.with_availability as DeviceSize; + let per_query_len = self.pool.query_type.result_len() + + flags.intersects(QueryResultFlags::WITH_AVAILABILITY) as DeviceSize; let required_len = per_query_len * count as DeviceSize; // VUID-vkGetQueryPoolResults-dataSize-00817 @@ -410,7 +413,7 @@ impl<'a> QueriesRange<'a> { QueryType::PipelineStatistics(_) => (), QueryType::Timestamp => { // VUID-vkGetQueryPoolResults-queryType-00818 - if flags.partial { + if flags.intersects(QueryResultFlags::PARTIAL) { return Err(GetResultsError::InvalidFlags); } } @@ -536,16 +539,21 @@ impl QueryType { /// Returns the number of [`QueryResultElement`]s that are needed to hold the result of a /// single query of this type. /// - /// - For `Occlusion` and `Timestamp` queries, this returns 1. - /// - For `PipelineStatistics` queries, this returns the number of statistics flags enabled. + /// - For [`Occlusion`] and [`Timestamp`] queries, this returns 1. + /// - For [`PipelineStatistics`] queries, this returns the number of statistics flags enabled. /// - /// If the results are retrieved with [`QueryResultFlags::with_availability`] enabled, then - /// an additional element is required per query. + /// If the results are retrieved with [`WITH_AVAILABILITY`] enabled, then an additional element + /// is required per query. + /// + /// [`Occlusion`]: QueryType::Occlusion + /// [`Timestamp`]: QueryType::Timestamp + /// [`PipelineStatistics`]: QueryType::PipelineStatistics + /// [`WITH_AVAILABILITY`]: QueryResultFlags::WITH_AVAILABILITY #[inline] - pub const fn result_len(&self) -> DeviceSize { + pub const fn result_len(self) -> DeviceSize { match self { Self::Occlusion | Self::Timestamp => 1, - Self::PipelineStatistics(flags) => flags.count(), + Self::PipelineStatistics(flags) => flags.count() as DeviceSize, } } } @@ -562,161 +570,118 @@ impl From for ash::vk::QueryType { } vulkan_bitflags! { - /// Flags that control how a query is to be executed. #[non_exhaustive] + + /// Flags that control how a query is to be executed. QueryControlFlags = QueryControlFlags(u32); /// For occlusion queries, specifies that the result must reflect the exact number of /// tests passed. If not enabled, the query may return a result of 1 even if more fragments /// passed the test. - precise = PRECISE, + PRECISE = PRECISE, } vulkan_bitflags! { - /// For pipeline statistics queries, the statistics that should be gathered. #[non_exhaustive] - QueryPipelineStatisticFlags = QueryPipelineStatisticFlags(u32); + + /// For pipeline statistics queries, the statistics that should be gathered. + QueryPipelineStatisticFlags impl { + /// Returns `true` if `self` contains any flags referring to compute operations. + #[inline] + pub const fn is_compute(self) -> bool { + self.intersects(QueryPipelineStatisticFlags::COMPUTE_SHADER_INVOCATIONS) + } + + /// Returns `true` if `self` contains any flags referring to graphics operations. + #[inline] + pub const fn is_graphics(self) -> bool { + self.intersects( + (QueryPipelineStatisticFlags::INPUT_ASSEMBLY_VERTICES) + .union(QueryPipelineStatisticFlags::INPUT_ASSEMBLY_PRIMITIVES) + .union(QueryPipelineStatisticFlags::VERTEX_SHADER_INVOCATIONS) + .union(QueryPipelineStatisticFlags::GEOMETRY_SHADER_INVOCATIONS) + .union(QueryPipelineStatisticFlags::GEOMETRY_SHADER_PRIMITIVES) + .union(QueryPipelineStatisticFlags::CLIPPING_INVOCATIONS) + .union(QueryPipelineStatisticFlags::CLIPPING_PRIMITIVES) + .union(QueryPipelineStatisticFlags::FRAGMENT_SHADER_INVOCATIONS) + .union(QueryPipelineStatisticFlags::TESSELLATION_CONTROL_SHADER_PATCHES) + .union(QueryPipelineStatisticFlags::TESSELLATION_EVALUATION_SHADER_INVOCATIONS), + ) + } + } + = QueryPipelineStatisticFlags(u32); /// Count the number of vertices processed by the input assembly. - input_assembly_vertices = INPUT_ASSEMBLY_VERTICES, + INPUT_ASSEMBLY_VERTICES = INPUT_ASSEMBLY_VERTICES, /// Count the number of primitives processed by the input assembly. - input_assembly_primitives = INPUT_ASSEMBLY_PRIMITIVES, + INPUT_ASSEMBLY_PRIMITIVES = INPUT_ASSEMBLY_PRIMITIVES, /// Count the number of times a vertex shader is invoked. - vertex_shader_invocations = VERTEX_SHADER_INVOCATIONS, + VERTEX_SHADER_INVOCATIONS = VERTEX_SHADER_INVOCATIONS, /// Count the number of times a geometry shader is invoked. - geometry_shader_invocations = GEOMETRY_SHADER_INVOCATIONS, + GEOMETRY_SHADER_INVOCATIONS = GEOMETRY_SHADER_INVOCATIONS, /// Count the number of primitives generated by geometry shaders. - geometry_shader_primitives = GEOMETRY_SHADER_PRIMITIVES, + GEOMETRY_SHADER_PRIMITIVES = GEOMETRY_SHADER_PRIMITIVES, /// Count the number of times the clipping stage is invoked on a primitive. - clipping_invocations = CLIPPING_INVOCATIONS, + CLIPPING_INVOCATIONS = CLIPPING_INVOCATIONS, /// Count the number of primitives that are output by the clipping stage. - clipping_primitives = CLIPPING_PRIMITIVES, + CLIPPING_PRIMITIVES = CLIPPING_PRIMITIVES, /// Count the number of times a fragment shader is invoked. - fragment_shader_invocations = FRAGMENT_SHADER_INVOCATIONS, + FRAGMENT_SHADER_INVOCATIONS = FRAGMENT_SHADER_INVOCATIONS, /// Count the number of patches processed by a tessellation control shader. - tessellation_control_shader_patches = TESSELLATION_CONTROL_SHADER_PATCHES, + TESSELLATION_CONTROL_SHADER_PATCHES = TESSELLATION_CONTROL_SHADER_PATCHES, /// Count the number of times a tessellation evaluation shader is invoked. - tessellation_evaluation_shader_invocations = TESSELLATION_EVALUATION_SHADER_INVOCATIONS, + TESSELLATION_EVALUATION_SHADER_INVOCATIONS = TESSELLATION_EVALUATION_SHADER_INVOCATIONS, /// Count the number of times a compute shader is invoked. - compute_shader_invocations = COMPUTE_SHADER_INVOCATIONS, + COMPUTE_SHADER_INVOCATIONS = COMPUTE_SHADER_INVOCATIONS, /* // TODO: document - task_shader_invocations = TASK_SHADER_INVOCATIONS_NV { + TASK_SHADER_INVOCATIONS = TASK_SHADER_INVOCATIONS_NV { device_extensions: [nv_mesh_shader], }, // TODO: document - mesh_shader_invocations = MESH_SHADER_INVOCATIONS_NV { + MESH_SHADER_INVOCATIONS = MESH_SHADER_INVOCATIONS_NV { device_extensions: [nv_mesh_shader], }, */ } -impl QueryPipelineStatisticFlags { - /// Returns the number of flags that are set to `true`. - #[inline] - pub const fn count(&self) -> DeviceSize { - let &Self { - input_assembly_vertices, - input_assembly_primitives, - vertex_shader_invocations, - geometry_shader_invocations, - geometry_shader_primitives, - clipping_invocations, - clipping_primitives, - fragment_shader_invocations, - tessellation_control_shader_patches, - tessellation_evaluation_shader_invocations, - compute_shader_invocations, - _ne: _, - } = self; - input_assembly_vertices as DeviceSize - + input_assembly_primitives as DeviceSize - + vertex_shader_invocations as DeviceSize - + geometry_shader_invocations as DeviceSize - + geometry_shader_primitives as DeviceSize - + clipping_invocations as DeviceSize - + clipping_primitives as DeviceSize - + fragment_shader_invocations as DeviceSize - + tessellation_control_shader_patches as DeviceSize - + tessellation_evaluation_shader_invocations as DeviceSize - + compute_shader_invocations as DeviceSize - } - - /// Returns `true` if any flags referring to compute operations are set to `true`. - #[inline] - pub const fn is_compute(&self) -> bool { - let &Self { - compute_shader_invocations, - .. - } = self; - compute_shader_invocations - } - - /// Returns `true` if any flags referring to graphics operations are set to `true`. - #[inline] - pub const fn is_graphics(&self) -> bool { - let &Self { - input_assembly_vertices, - input_assembly_primitives, - vertex_shader_invocations, - geometry_shader_invocations, - geometry_shader_primitives, - clipping_invocations, - clipping_primitives, - fragment_shader_invocations, - tessellation_control_shader_patches, - tessellation_evaluation_shader_invocations, - .. - } = self; - input_assembly_vertices - || input_assembly_primitives - || vertex_shader_invocations - || geometry_shader_invocations - || geometry_shader_primitives - || clipping_invocations - || clipping_primitives - || fragment_shader_invocations - || tessellation_control_shader_patches - || tessellation_evaluation_shader_invocations - } -} - vulkan_bitflags! { + #[non_exhaustive] + /// Flags to control how the results of a query should be retrieved. /// /// `VK_QUERY_RESULT_64_BIT` is not included, as it is determined automatically via the /// [`QueryResultElement`] trait. - #[non_exhaustive] QueryResultFlags = QueryResultFlags(u32); /// Wait for the results to become available before writing the results. - wait = WAIT, + WAIT = WAIT, /// Write an additional element to the end of each query's results, indicating the availability /// of the results: /// - Nonzero: The results are available, and have been written to the element(s) preceding. /// - Zero: The results are not yet available, and have not been written. - with_availability = WITH_AVAILABILITY, + WITH_AVAILABILITY = WITH_AVAILABILITY, /// Allow writing partial results to the buffer, instead of waiting until they are fully /// available. - partial = PARTIAL, + PARTIAL = PARTIAL, /* // TODO: document - with_status = WITH_STATUS_KHR { + WITH_STATUS = WITH_STATUS_KHR { device_extensions: [khr_video_queue], }, */ diff --git a/vulkano/src/render_pass/create.rs b/vulkano/src/render_pass/create.rs index bd2e060e..69ea8467 100644 --- a/vulkano/src/render_pass/create.rs +++ b/vulkano/src/render_pass/create.rs @@ -13,7 +13,8 @@ use super::{ }; use crate::{ device::Device, - image::{ImageLayout, SampleCount}, + format::FormatFeatures, + image::{ImageAspects, ImageLayout, SampleCount}, sync::PipelineStages, OomError, RequirementNotMet, RequiresOneOf, Version, VulkanError, VulkanObject, }; @@ -98,7 +99,7 @@ impl RenderPass { // VUID-VkAttachmentDescription2-finalLayout-parameter layout.validate_device(device)?; - if aspects.depth || aspects.stencil { + if aspects.intersects(ImageAspects::DEPTH | ImageAspects::STENCIL) { // VUID-VkAttachmentDescription2-format-03281 // VUID-VkAttachmentDescription2-format-03283 if matches!(layout, ImageLayout::ColorAttachmentOptimal) { @@ -285,7 +286,7 @@ impl RenderPass { let (atch, features, _first_use) = check_attachment(atch_ref)?; // VUID-VkSubpassDescription2-pColorAttachments-02898 - if !features.color_attachment { + if !features.intersects(FormatFeatures::COLOR_ATTACHMENT) { return Err( RenderPassCreationError::SubpassAttachmentFormatUsageNotSupported { subpass: subpass_num, @@ -348,7 +349,7 @@ impl RenderPass { let (atch, features, _first_use) = check_attachment(atch_ref)?; // VUID-VkSubpassDescription2-pDepthStencilAttachment-02900 - if !features.depth_stencil_attachment { + if !features.intersects(FormatFeatures::DEPTH_STENCIL_ATTACHMENT) { return Err( RenderPassCreationError::SubpassAttachmentFormatUsageNotSupported { subpass: subpass_num, @@ -420,7 +421,9 @@ impl RenderPass { let (atch, features, first_use) = check_attachment(atch_ref)?; // VUID-VkSubpassDescription2-pInputAttachments-02897 - if !(features.color_attachment || features.depth_stencil_attachment) { + if !features.intersects( + FormatFeatures::COLOR_ATTACHMENT | FormatFeatures::DEPTH_STENCIL_ATTACHMENT, + ) { return Err( RenderPassCreationError::SubpassAttachmentFormatUsageNotSupported { subpass: subpass_num, @@ -458,7 +461,10 @@ impl RenderPass { || device.enabled_extensions().khr_maintenance2) { return Err(RenderPassCreationError::RequirementNotMet { - required_for: "`create_info.subpasses` has an element, where `input_attachments` has an element that is `Some(atch_ref)`, where `atch_ref.aspects` does not match the aspects of the attachment itself", + required_for: "`create_info.subpasses` has an element, where \ + `input_attachments` has an element that is `Some(atch_ref)`, \ + where `atch_ref.aspects` does not match the aspects of the \ + attachment itself", requires_one_of: RequiresOneOf { api_version: Some(Version::V1_1), device_extensions: &["khr_create_renderpass2", "khr_maintenance2"], @@ -470,7 +476,7 @@ impl RenderPass { // VUID-VkSubpassDescription2-attachment-02801 // VUID-VkSubpassDescription2-attachment-04563 // VUID-VkRenderPassCreateInfo2-attachment-02525 - if !atch_aspects.contains(&atch_ref.aspects) { + if !atch_aspects.contains(atch_ref.aspects) { return Err( RenderPassCreationError::SubpassInputAttachmentAspectsNotCompatible { subpass: subpass_num, @@ -512,7 +518,7 @@ impl RenderPass { let (atch, features, _first_use) = check_attachment(atch_ref)?; // VUID-VkSubpassDescription2-pResolveAttachments-02899 - if !features.color_attachment { + if !features.intersects(FormatFeatures::COLOR_ATTACHMENT) { return Err( RenderPassCreationError::SubpassAttachmentFormatUsageNotSupported { subpass: subpass_num, @@ -637,7 +643,9 @@ impl RenderPass { if !device.enabled_features().synchronization2 { if stages.is_2() { return Err(RenderPassCreationError::RequirementNotMet { - required_for: "`create_info.dependencies` has an element where `src_stages` or `dst_stages` has bits set from `VkPipelineStageFlagBits2`", + required_for: "`create_info.dependencies` has an element where \ + `src_stages` or `dst_stages` contains flags from \ + `VkPipelineStageFlagBits2`", requires_one_of: RequiresOneOf { features: &["synchronization2"], ..Default::default() @@ -647,7 +655,9 @@ impl RenderPass { if access.is_2() { return Err(RenderPassCreationError::RequirementNotMet { - required_for: "`create_info.dependencies` has an element where `src_access` or `dst_access` has bits set from `VkAccessFlagBits2`", + required_for: "`create_info.dependencies` has an element where \ + `src_access` or `dst_access` contains flags from \ + `VkAccessFlagBits2`", requires_one_of: RequiresOneOf { features: &["synchronization2"], ..Default::default() @@ -663,7 +673,9 @@ impl RenderPass { if stages.is_2() { return Err(RenderPassCreationError::RequirementNotMet { - required_for: "`create_info.dependencies` has an element where `src_stages` or `dst_stages` has bits set from `VkPipelineStageFlagBits2`", + required_for: "`create_info.dependencies` has an element where \ + `src_stages` or `dst_stages` contains flags from \ + `VkPipelineStageFlagBits2`", requires_one_of: RequiresOneOf { api_version: Some(Version::V1_2), device_extensions: &["khr_create_renderpass2"], @@ -674,7 +686,9 @@ impl RenderPass { if access.is_2() { return Err(RenderPassCreationError::RequirementNotMet { - required_for: "`create_info.dependencies` has an element where `src_access` or `dst_access` has bits set from `VkAccessFlagBits2`", + required_for: "`create_info.dependencies` has an element where \ + `src_access` or `dst_access` contains flags from \ + `VkAccessFlagBits2`", requires_one_of: RequiresOneOf { api_version: Some(Version::V1_2), device_extensions: &["khr_create_renderpass2"], @@ -694,9 +708,12 @@ impl RenderPass { // VUID-VkMemoryBarrier2-srcStageMask-03929 // VUID-VkMemoryBarrier2-dstStageMask-03929 - if stages.geometry_shader && !device.enabled_features().geometry_shader { + if stages.intersects(PipelineStages::GEOMETRY_SHADER) + && !device.enabled_features().geometry_shader + { return Err(RenderPassCreationError::RequirementNotMet { - required_for: "`create_info.dependencies` has an element where `stages.geometry_shader` is set", + required_for: "`create_info.dependencies` has an element where `stages` \ + contains `PipelineStages::GEOMETRY_SHADER`", requires_one_of: RequiresOneOf { features: &["geometry_shader"], ..Default::default() @@ -706,11 +723,15 @@ impl RenderPass { // VUID-VkMemoryBarrier2-srcStageMask-03930 // VUID-VkMemoryBarrier2-dstStageMask-03930 - if (stages.tessellation_control_shader || stages.tessellation_evaluation_shader) - && !device.enabled_features().tessellation_shader + if stages.intersects( + PipelineStages::TESSELLATION_CONTROL_SHADER + | PipelineStages::TESSELLATION_EVALUATION_SHADER, + ) && !device.enabled_features().tessellation_shader { return Err(RenderPassCreationError::RequirementNotMet { - required_for: "`create_info.dependencies` has an element where `stages.tessellation_control_shader` or `stages.tessellation_evaluation_shader` are set", + required_for: "`create_info.dependencies` has an element where `stages` \ + contains `PipelineStages::TESSELLATION_CONTROL_SHADER` or \ + `PipelineStages::TESSELLATION_EVALUATION_SHADER`", requires_one_of: RequiresOneOf { features: &["tessellation_shader"], ..Default::default() @@ -720,10 +741,12 @@ impl RenderPass { // VUID-VkMemoryBarrier2-srcStageMask-03931 // VUID-VkMemoryBarrier2-dstStageMask-03931 - if stages.conditional_rendering && !device.enabled_features().conditional_rendering + if stages.intersects(PipelineStages::CONDITIONAL_RENDERING) + && !device.enabled_features().conditional_rendering { return Err(RenderPassCreationError::RequirementNotMet { - required_for: "`create_info.dependencies` has an element where `stages.conditional_rendering` is set", + required_for: "`create_info.dependencies` has an element where `stages` \ + contains `PipelineStages::CONDITIONAL_RENDERING`", requires_one_of: RequiresOneOf { features: &["conditional_rendering"], ..Default::default() @@ -733,11 +756,12 @@ impl RenderPass { // VUID-VkMemoryBarrier2-srcStageMask-03932 // VUID-VkMemoryBarrier2-dstStageMask-03932 - if stages.fragment_density_process + if stages.intersects(PipelineStages::FRAGMENT_DENSITY_PROCESS) && !device.enabled_features().fragment_density_map { return Err(RenderPassCreationError::RequirementNotMet { - required_for: "`create_info.dependencies` has an element where `stages.fragment_density_process` is set", + required_for: "`create_info.dependencies` has an element where `stages` \ + contains `PipelineStages::FRAGMENT_DENSITY_PROCESS`", requires_one_of: RequiresOneOf { features: &["fragment_density_map"], ..Default::default() @@ -747,9 +771,12 @@ impl RenderPass { // VUID-VkMemoryBarrier2-srcStageMask-03933 // VUID-VkMemoryBarrier2-dstStageMask-03933 - if stages.transform_feedback && !device.enabled_features().transform_feedback { + if stages.intersects(PipelineStages::TRANSFORM_FEEDBACK) + && !device.enabled_features().transform_feedback + { return Err(RenderPassCreationError::RequirementNotMet { - required_for: "`create_info.dependencies` has an element where `stages.transform_feedback` is set", + required_for: "`create_info.dependencies` has an element where `stages` \ + contains `PipelineStages::TRANSFORM_FEEDBACK`", requires_one_of: RequiresOneOf { features: &["transform_feedback"], ..Default::default() @@ -759,9 +786,12 @@ impl RenderPass { // VUID-VkMemoryBarrier2-srcStageMask-03934 // VUID-VkMemoryBarrier2-dstStageMask-03934 - if stages.mesh_shader && !device.enabled_features().mesh_shader { + if stages.intersects(PipelineStages::MESH_SHADER) + && !device.enabled_features().mesh_shader + { return Err(RenderPassCreationError::RequirementNotMet { - required_for: "`create_info.dependencies` has an element where `stages.mesh_shader` is set", + required_for: "`create_info.dependencies` has an element where `stages` \ + contains `PipelineStages::MESH_SHADER`", requires_one_of: RequiresOneOf { features: &["mesh_shader"], ..Default::default() @@ -771,9 +801,12 @@ impl RenderPass { // VUID-VkMemoryBarrier2-srcStageMask-03935 // VUID-VkMemoryBarrier2-dstStageMask-03935 - if stages.task_shader && !device.enabled_features().task_shader { + if stages.intersects(PipelineStages::TASK_SHADER) + && !device.enabled_features().task_shader + { return Err(RenderPassCreationError::RequirementNotMet { - required_for: "`create_info.dependencies` has an element where `stages.task_shader` is set", + required_for: "`create_info.dependencies` has an element where `stages` \ + contains `PipelineStages::TASK_SHADER`", requires_one_of: RequiresOneOf { features: &["task_shader"], ..Default::default() @@ -783,12 +816,13 @@ impl RenderPass { // VUID-VkMemoryBarrier2-shadingRateImage-07316 // VUID-VkMemoryBarrier2-shadingRateImage-07316 - if stages.fragment_shading_rate_attachment + if stages.intersects(PipelineStages::FRAGMENT_SHADING_RATE_ATTACHMENT) && !(device.enabled_features().attachment_fragment_shading_rate || device.enabled_features().shading_rate_image) { return Err(RenderPassCreationError::RequirementNotMet { - required_for: "`create_info.dependencies` has an element where `stages.fragment_shading_rate_attachment` is set", + required_for: "`create_info.dependencies` has an element where `stages` \ + contains `PipelineStages::FRAGMENT_SHADING_RATE_ATTACHMENT`", requires_one_of: RequiresOneOf { features: &["attachment_fragment_shading_rate", "shading_rate_image"], ..Default::default() @@ -798,9 +832,12 @@ impl RenderPass { // VUID-VkMemoryBarrier2-srcStageMask-04957 // VUID-VkMemoryBarrier2-dstStageMask-04957 - if stages.subpass_shading && !device.enabled_features().subpass_shading { + if stages.intersects(PipelineStages::SUBPASS_SHADING) + && !device.enabled_features().subpass_shading + { return Err(RenderPassCreationError::RequirementNotMet { - required_for: "`create_info.dependencies` has an element where `stages.subpass_shading` is set", + required_for: "`create_info.dependencies` has an element where `stages` \ + contains `PipelineStages::SUBPASS_SHADING`", requires_one_of: RequiresOneOf { features: &["subpass_shading"], ..Default::default() @@ -810,9 +847,12 @@ impl RenderPass { // VUID-VkMemoryBarrier2-srcStageMask-04995 // VUID-VkMemoryBarrier2-dstStageMask-04995 - if stages.invocation_mask && !device.enabled_features().invocation_mask { + if stages.intersects(PipelineStages::INVOCATION_MASK) + && !device.enabled_features().invocation_mask + { return Err(RenderPassCreationError::RequirementNotMet { - required_for: "`create_info.dependencies` has an element where `stages.invocation_mask` is set", + required_for: "`create_info.dependencies` has an element where `stages` \ + contains `PipelineStages::INVOCATION_MASK`", requires_one_of: RequiresOneOf { features: &["invocation_mask"], ..Default::default() @@ -824,8 +864,8 @@ impl RenderPass { // VUID-VkSubpassDependency2-dstStageMask-03937 if stages.is_empty() && !device.enabled_features().synchronization2 { return Err(RenderPassCreationError::RequirementNotMet { - required_for: - "`create_info.dependencies` has an element where `stages` is empty", + required_for: "`create_info.dependencies` has an element where `stages` \ + is empty", requires_one_of: RequiresOneOf { features: &["synchronization2"], ..Default::default() @@ -835,7 +875,7 @@ impl RenderPass { // VUID-VkSubpassDependency2-srcAccessMask-03088 // VUID-VkSubpassDependency2-dstAccessMask-03089 - if !stages.supported_access().contains(&access) { + if !stages.supported_access().contains(access) { return Err( RenderPassCreationError::DependencyAccessNotSupportedByStages { dependency: dependency_num, @@ -871,23 +911,21 @@ impl RenderPass { }); } - let remaining_stages = PipelineStages { - draw_indirect: false, - //index_input: false, - //vertex_attribute_input: false, - vertex_shader: false, - tessellation_control_shader: false, - tessellation_evaluation_shader: false, - geometry_shader: false, - //transform_feedback: false, - //fragment_shading_rate_attachment: false, - early_fragment_tests: false, - fragment_shader: false, - late_fragment_tests: false, - color_attachment_output: false, - all_graphics: false, - ..stages - }; + let remaining_stages = stages + - (PipelineStages::DRAW_INDIRECT + | PipelineStages::INDEX_INPUT + | PipelineStages::VERTEX_ATTRIBUTE_INPUT + | PipelineStages::VERTEX_SHADER + | PipelineStages::TESSELLATION_CONTROL_SHADER + | PipelineStages::TESSELLATION_EVALUATION_SHADER + | PipelineStages::GEOMETRY_SHADER + | PipelineStages::TRANSFORM_FEEDBACK + | PipelineStages::FRAGMENT_SHADING_RATE_ATTACHMENT + | PipelineStages::EARLY_FRAGMENT_TESTS + | PipelineStages::FRAGMENT_SHADER + | PipelineStages::LATE_FRAGMENT_TESTS + | PipelineStages::COLOR_ATTACHMENT_OUTPUT + | PipelineStages::ALL_GRAPHICS); // VUID-VkRenderPassCreateInfo2-pDependencies-03054 // VUID-VkRenderPassCreateInfo2-pDependencies-03055 @@ -920,16 +958,13 @@ impl RenderPass { } if src_subpass == dst_subpass { - let framebuffer_stages = PipelineStages { - early_fragment_tests: true, - fragment_shader: true, - late_fragment_tests: true, - color_attachment_output: true, - ..PipelineStages::empty() - }; + let framebuffer_stages = PipelineStages::EARLY_FRAGMENT_TESTS + | PipelineStages::FRAGMENT_SHADER + | PipelineStages::LATE_FRAGMENT_TESTS + | PipelineStages::COLOR_ATTACHMENT_OUTPUT; // VUID-VkSubpassDependency2-srcSubpass-06810 - if src_stages.intersects(&framebuffer_stages) + if src_stages.intersects(framebuffer_stages) && !(dst_stages - framebuffer_stages).is_empty() { return Err( @@ -940,8 +975,8 @@ impl RenderPass { } // VUID-VkSubpassDependency2-srcSubpass-02245 - if src_stages.intersects(&framebuffer_stages) - && dst_stages.intersects(&framebuffer_stages) + if src_stages.intersects(framebuffer_stages) + && dst_stages.intersects(framebuffer_stages) && !by_region { return Err( diff --git a/vulkano/src/render_pass/framebuffer.rs b/vulkano/src/render_pass/framebuffer.rs index f97c2ed3..b5a3c14e 100644 --- a/vulkano/src/render_pass/framebuffer.rs +++ b/vulkano/src/render_pass/framebuffer.rs @@ -11,7 +11,7 @@ use super::RenderPass; use crate::{ device::{Device, DeviceOwned}, format::Format, - image::{view::ImageViewType, ImageDimensions, ImageViewAbstract, SampleCount}, + image::{view::ImageViewType, ImageDimensions, ImageUsage, ImageViewAbstract, SampleCount}, OomError, VulkanError, VulkanObject, }; use smallvec::SmallVec; @@ -131,7 +131,7 @@ impl Framebuffer { .flatten() .any(|atch_ref| atch_ref.attachment == attachment_num) { - if !image_view.usage().color_attachment { + if !image_view.usage().intersects(ImageUsage::COLOR_ATTACHMENT) { return Err(FramebufferCreationError::AttachmentMissingUsage { attachment: attachment_num, usage: "color_attachment", @@ -142,7 +142,10 @@ impl Framebuffer { // VUID-VkFramebufferCreateInfo-pAttachments-02633 if let Some(atch_ref) = &subpass.depth_stencil_attachment { if atch_ref.attachment == attachment_num { - if !image_view.usage().depth_stencil_attachment { + if !image_view + .usage() + .intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT) + { return Err(FramebufferCreationError::AttachmentMissingUsage { attachment: attachment_num, usage: "depth_stencil", @@ -158,7 +161,7 @@ impl Framebuffer { .flatten() .any(|atch_ref| atch_ref.attachment == attachment_num) { - if !image_view.usage().input_attachment { + if !image_view.usage().intersects(ImageUsage::INPUT_ATTACHMENT) { return Err(FramebufferCreationError::AttachmentMissingUsage { attachment: attachment_num, usage: "input_attachment", diff --git a/vulkano/src/render_pass/macros.rs b/vulkano/src/render_pass/macros.rs index 3a8edd1b..9d4a4941 100644 --- a/vulkano/src/render_pass/macros.rs +++ b/vulkano/src/render_pass/macros.rs @@ -154,24 +154,12 @@ macro_rules! ordered_passes_renderpass { let dependencies: Vec<_> = (0..subpasses.len().saturating_sub(1) as u32) .map(|id| { // TODO: correct values - let src_stages = $crate::sync::PipelineStages { - all_graphics: true, - ..$crate::sync::PipelineStages::empty() - }; - let dst_stages = $crate::sync::PipelineStages { - all_graphics: true, - ..$crate::sync::PipelineStages::empty() - }; - let src_access = $crate::sync::AccessFlags { - memory_read: true, - memory_write: true, - ..$crate::sync::AccessFlags::empty() - }; - let dst_access = $crate::sync::AccessFlags { - memory_read: true, - memory_write: true, - ..$crate::sync::AccessFlags::empty() - }; + let src_stages = $crate::sync::PipelineStages::ALL_GRAPHICS; + let dst_stages = $crate::sync::PipelineStages::ALL_GRAPHICS; + let src_access = $crate::sync::AccessFlags::MEMORY_READ + | $crate::sync::AccessFlags::MEMORY_WRITE; + let dst_access = $crate::sync::AccessFlags::MEMORY_READ + | $crate::sync::AccessFlags::MEMORY_WRITE; $crate::render_pass::SubpassDependency { src_subpass: id.into(), diff --git a/vulkano/src/render_pass/mod.rs b/vulkano/src/render_pass/mod.rs index 88b1c0ea..33278b6c 100644 --- a/vulkano/src/render_pass/mod.rs +++ b/vulkano/src/render_pass/mod.rs @@ -33,7 +33,7 @@ use crate::{ device::{Device, DeviceOwned}, format::Format, image::{ImageAspects, ImageLayout, SampleCount}, - macros::{vulkan_bitflags, vulkan_enum}, + macros::{vulkan_bitflags_enum, vulkan_enum}, shader::ShaderInterface, sync::{AccessFlags, PipelineStages}, Version, VulkanObject, @@ -619,7 +619,7 @@ impl Subpass { self.attachment_desc(atch_num) .format - .map_or(false, |f| f.aspects().depth) + .map_or(false, |f| f.aspects().intersects(ImageAspects::DEPTH)) } /// Returns true if the subpass has a depth attachment or a depth-stencil attachment whose @@ -643,7 +643,7 @@ impl Subpass { self.attachment_desc(atch_num) .format - .map_or(false, |f| f.aspects().depth) + .map_or(false, |f| f.aspects().intersects(ImageAspects::DEPTH)) } /// Returns true if the subpass has a stencil attachment or a depth-stencil attachment. @@ -657,7 +657,7 @@ impl Subpass { self.attachment_desc(atch_num) .format - .map_or(false, |f| f.aspects().stencil) + .map_or(false, |f| f.aspects().intersects(ImageAspects::STENCIL)) } /// Returns true if the subpass has a stencil attachment or a depth-stencil attachment whose @@ -682,7 +682,7 @@ impl Subpass { self.attachment_desc(atch_num) .format - .map_or(false, |f| f.aspects().stencil) + .map_or(false, |f| f.aspects().intersects(ImageAspects::STENCIL)) } /// Returns the number of samples in the color and/or depth/stencil attachments. Returns `None` @@ -1087,8 +1087,9 @@ impl Default for SubpassDependency { } vulkan_enum! { - /// Describes what the implementation should do with an attachment at the start of the subpass. #[non_exhaustive] + + /// Describes what the implementation should do with an attachment at the start of the subpass. LoadOp = AttachmentLoadOp(i32); /// The content of the attachment will be loaded from memory. This is what you want if you want @@ -1122,9 +1123,10 @@ vulkan_enum! { } vulkan_enum! { + #[non_exhaustive] + /// Describes what the implementation should do with an attachment after all the subpasses have /// completed. - #[non_exhaustive] StoreOp = AttachmentStoreOp(i32); /// The attachment will be stored. This is what you usually want. @@ -1152,62 +1154,37 @@ vulkan_enum! { */ } -vulkan_enum! { - /// Possible resolve modes for attachments. +vulkan_bitflags_enum! { #[non_exhaustive] - ResolveMode = ResolveModeFlags(u32); + + /// A set of [`ResolveMode`] values. + ResolveModes, + + /// Possible resolve modes for attachments. + ResolveMode, + + = ResolveModeFlags(u32); /// The resolved sample is taken from sample number zero, the other samples are ignored. /// /// This mode is supported for depth and stencil formats, and for color images with an integer /// format. - SampleZero = SAMPLE_ZERO, + SAMPLE_ZERO, SampleZero = SAMPLE_ZERO, /// The resolved sample is calculated from the average of the samples. /// /// This mode is supported for depth formats, and for color images with a non-integer format. - Average = AVERAGE, + AVERAGE, Average = AVERAGE, /// The resolved sample is calculated from the minimum of the samples. /// /// This mode is supported for depth and stencil formats only. - Min = MIN, + MIN, Min = MIN, /// The resolved sample is calculated from the maximum of the samples. /// /// This mode is supported for depth and stencil formats only. - Max = MAX, -} - -vulkan_bitflags! { - // TODO: document - #[non_exhaustive] - ResolveModes = ResolveModeFlags(u32); - - // TODO: document - sample_zero = SAMPLE_ZERO, - - // TODO: document - average = AVERAGE, - - // TODO: document - min = MIN, - - // TODO: document - max = MAX, -} - -impl ResolveModes { - /// Returns whether `self` contains the given `mode`. - #[inline] - pub fn contains_mode(&self, mode: ResolveMode) -> bool { - match mode { - ResolveMode::SampleZero => self.sample_zero, - ResolveMode::Average => self.average, - ResolveMode::Min => self.min, - ResolveMode::Max => self.max, - } - } + MAX, Max = MAX, } #[cfg(test)] diff --git a/vulkano/src/sampler/mod.rs b/vulkano/src/sampler/mod.rs index da2338e6..e90405a8 100644 --- a/vulkano/src/sampler/mod.rs +++ b/vulkano/src/sampler/mod.rs @@ -49,7 +49,8 @@ pub mod ycbcr; use self::ycbcr::SamplerYcbcrConversion; use crate::{ device::{Device, DeviceOwned}, - image::{view::ImageViewType, ImageViewAbstract}, + format::FormatFeatures, + image::{view::ImageViewType, ImageAspects, ImageViewAbstract}, macros::vulkan_enum, pipeline::graphics::depth_stencil::CompareOp, shader::ShaderScalarType, @@ -167,7 +168,8 @@ impl Sampler { && !device.enabled_extensions().khr_sampler_mirror_clamp_to_edge { return Err(SamplerCreationError::RequirementNotMet { - required_for: "`create_info.address_mode` contains `SamplerAddressMode::MirrorClampToEdge`", + required_for: "`create_info.address_mode` contains \ + `SamplerAddressMode::MirrorClampToEdge`", requires_one_of: RequiresOneOf { features: &["sampler_mirror_clamp_to_edge"], device_extensions: &["khr_sampler_mirror_clamp_to_edge"], @@ -294,32 +296,32 @@ impl Sampler { } } - let mut sampler_reduction_mode_create_info = if reduction_mode - != SamplerReductionMode::WeightedAverage - { - if !(device.enabled_features().sampler_filter_minmax - || device.enabled_extensions().ext_sampler_filter_minmax) - { - return Err(SamplerCreationError::RequirementNotMet { - required_for: "`create_info.reduction_mode` is not `SamplerReductionMode::WeightedAverage`", + let mut sampler_reduction_mode_create_info = + if reduction_mode != SamplerReductionMode::WeightedAverage { + if !(device.enabled_features().sampler_filter_minmax + || device.enabled_extensions().ext_sampler_filter_minmax) + { + return Err(SamplerCreationError::RequirementNotMet { + required_for: "`create_info.reduction_mode` is not \ + `SamplerReductionMode::WeightedAverage`", requires_one_of: RequiresOneOf { features: &["sampler_filter_minmax"], device_extensions: &["ext_sampler_filter_minmax"], ..Default::default() }, }); - } + } - // VUID-VkSamplerReductionModeCreateInfo-reductionMode-parameter - reduction_mode.validate_device(&device)?; + // VUID-VkSamplerReductionModeCreateInfo-reductionMode-parameter + reduction_mode.validate_device(&device)?; - Some(ash::vk::SamplerReductionModeCreateInfo { - reduction_mode: reduction_mode.into(), - ..Default::default() - }) - } else { - None - }; + Some(ash::vk::SamplerReductionModeCreateInfo { + reduction_mode: reduction_mode.into(), + ..Default::default() + }) + } else { + None + }; // Don't need to check features because you can't create a conversion object without the // feature anyway. @@ -337,10 +339,10 @@ impl Sampler { }; // VUID-VkSamplerCreateInfo-minFilter-01645 - if !potential_format_features - .sampled_image_ycbcr_conversion_separate_reconstruction_filter - && !(mag_filter == sampler_ycbcr_conversion.chroma_filter() - && min_filter == sampler_ycbcr_conversion.chroma_filter()) + if !potential_format_features.intersects( + FormatFeatures::SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER, + ) && !(mag_filter == sampler_ycbcr_conversion.chroma_filter() + && min_filter == sampler_ycbcr_conversion.chroma_filter()) { return Err( SamplerCreationError::SamplerYcbcrConversionChromaFilterMismatch { @@ -521,18 +523,28 @@ impl Sampler { if self.compare.is_some() { // VUID-vkCmdDispatch-None-06479 - if !image_view.format_features().sampled_image_depth_comparison { + if !image_view + .format_features() + .intersects(FormatFeatures::SAMPLED_IMAGE_DEPTH_COMPARISON) + { return Err(SamplerImageViewIncompatibleError::DepthComparisonNotSupported); } // The SPIR-V instruction is one of the OpImage*Dref* instructions, the image // view format is one of the depth/stencil formats, and the image view aspect // is not VK_IMAGE_ASPECT_DEPTH_BIT. - if !image_view.subresource_range().aspects.depth { + if !image_view + .subresource_range() + .aspects + .intersects(ImageAspects::DEPTH) + { return Err(SamplerImageViewIncompatibleError::DepthComparisonWrongAspect); } } else { - if !image_view.format_features().sampled_image_filter_linear { + if !image_view + .format_features() + .intersects(FormatFeatures::SAMPLED_IMAGE_FILTER_LINEAR) + { // VUID-vkCmdDispatch-magFilter-04553 if self.mag_filter == Filter::Linear || self.min_filter == Filter::Linear { return Err(SamplerImageViewIncompatibleError::FilterLinearNotSupported); @@ -547,7 +559,10 @@ impl Sampler { if self.mag_filter == Filter::Cubic || self.min_filter == Filter::Cubic { // VUID-vkCmdDispatch-None-02692 - if !image_view.format_features().sampled_image_filter_cubic { + if !image_view + .format_features() + .intersects(FormatFeatures::SAMPLED_IMAGE_FILTER_CUBIC) + { return Err(SamplerImageViewIncompatibleError::FilterCubicNotSupported); } @@ -569,11 +584,16 @@ impl Sampler { if let Some(border_color) = self.border_color { let aspects = image_view.subresource_range().aspects; 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() - } else if aspects.depth { + } else if aspects.intersects(ImageAspects::DEPTH) { image_view.format().unwrap().type_depth().unwrap() - } else if aspects.stencil { + } else if aspects.intersects(ImageAspects::STENCIL) { image_view.format().unwrap().type_stencil().unwrap() } else { // Per `ImageViewBuilder::aspects` and @@ -1274,8 +1294,9 @@ impl From for ash::vk::ComponentMapping { } vulkan_enum! { - /// Describes the value that an individual component must return when being accessed. #[non_exhaustive] + + /// Describes the value that an individual component must return when being accessed. ComponentSwizzle = ComponentSwizzle(i32); /// Returns the value that this component should normally have. @@ -1310,8 +1331,9 @@ impl Default for ComponentSwizzle { } vulkan_enum! { - /// Describes how the color of each pixel should be determined. #[non_exhaustive] + + /// Describes how the color of each pixel should be determined. Filter = Filter(i32); /// The pixel whose center is nearest to the requested coordinates is taken from the source @@ -1336,8 +1358,9 @@ vulkan_enum! { } vulkan_enum! { - /// Describes which mipmap from the source to use. #[non_exhaustive] + + /// Describes which mipmap from the source to use. SamplerMipmapMode = SamplerMipmapMode(i32); /// Use the mipmap whose dimensions are the nearest to the dimensions of the destination. @@ -1349,9 +1372,10 @@ vulkan_enum! { } vulkan_enum! { + #[non_exhaustive] + /// How the sampler should behave when it needs to access a pixel that is out of range of the /// texture. - #[non_exhaustive] SamplerAddressMode = SamplerAddressMode(i32); /// Repeat the texture. In other words, the pixel at coordinate `x + 1.0` is the same as the @@ -1390,12 +1414,13 @@ vulkan_enum! { } vulkan_enum! { + #[non_exhaustive] + /// The color to use for the border of an image. /// /// Only relevant if you use `ClampToBorder`. /// /// Using a border color restricts the sampler to either floating-point images or integer images. - #[non_exhaustive] BorderColor = BorderColor(i32); /// The value `(0.0, 0.0, 0.0, 0.0)`. Can only be used with floating-point images. @@ -1431,9 +1456,10 @@ vulkan_enum! { } vulkan_enum! { + #[non_exhaustive] + /// Describes how the value sampled from a mipmap should be calculated from the selected /// pixels, for the `Linear` and `Cubic` filters. - #[non_exhaustive] SamplerReductionMode = SamplerReductionMode(i32); /// Calculates a weighted average of the selected pixels. For `Linear` filtering the pixels diff --git a/vulkano/src/sampler/ycbcr.rs b/vulkano/src/sampler/ycbcr.rs index ff6ac0ae..ccf82a08 100644 --- a/vulkano/src/sampler/ycbcr.rs +++ b/vulkano/src/sampler/ycbcr.rs @@ -91,7 +91,7 @@ use crate::{ device::{Device, DeviceOwned}, - format::{ChromaSampling, Format, NumericType}, + format::{ChromaSampling, Format, FormatFeatures, NumericType}, macros::vulkan_enum, sampler::{ComponentMapping, ComponentSwizzle, Filter}, OomError, RequirementNotMet, RequiresOneOf, Version, VulkanError, VulkanObject, @@ -143,7 +143,7 @@ impl SamplerYcbcrConversion { if !device.enabled_features().sampler_ycbcr_conversion { return Err(SamplerYcbcrConversionCreationError::RequirementNotMet { - required_for: "`SamplerYcbcrConversion`", + required_for: "`SamplerYcbcrConversion::new`", requires_one_of: RequiresOneOf { features: &["sampler_ycbcr_conversion"], ..Default::default() @@ -205,9 +205,9 @@ impl SamplerYcbcrConversion { }; // VUID-VkSamplerYcbcrConversionCreateInfo-format-01650 - if !(potential_format_features.midpoint_chroma_samples - || potential_format_features.cosited_chroma_samples) - { + if !potential_format_features.intersects( + FormatFeatures::MIDPOINT_CHROMA_SAMPLES | FormatFeatures::COSITED_CHROMA_SAMPLES, + ) { return Err(SamplerYcbcrConversionCreationError::FormatNotSupported); } @@ -224,7 +224,9 @@ impl SamplerYcbcrConversion { match offset { ChromaLocation::CositedEven => { // VUID-VkSamplerYcbcrConversionCreateInfo-xChromaOffset-01651 - if !potential_format_features.cosited_chroma_samples { + if !potential_format_features + .intersects(FormatFeatures::COSITED_CHROMA_SAMPLES) + { return Err( SamplerYcbcrConversionCreationError::FormatChromaOffsetNotSupported, ); @@ -232,7 +234,9 @@ impl SamplerYcbcrConversion { } ChromaLocation::Midpoint => { // VUID-VkSamplerYcbcrConversionCreateInfo-xChromaOffset-01652 - if !potential_format_features.midpoint_chroma_samples { + if !potential_format_features + .intersects(FormatFeatures::MIDPOINT_CHROMA_SAMPLES) + { return Err( SamplerYcbcrConversionCreationError::FormatChromaOffsetNotSupported, ); @@ -292,8 +296,8 @@ impl SamplerYcbcrConversion { // VUID-VkSamplerYcbcrConversionCreateInfo-forceExplicitReconstruction-01656 if force_explicit_reconstruction - && !potential_format_features - .sampled_image_ycbcr_conversion_chroma_reconstruction_explicit_forceable + && !potential_format_features.intersects(FormatFeatures:: + SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE) { return Err( SamplerYcbcrConversionCreationError::FormatForceExplicitReconstructionNotSupported, @@ -304,7 +308,9 @@ impl SamplerYcbcrConversion { Filter::Nearest => (), Filter::Linear => { // VUID-VkSamplerYcbcrConversionCreateInfo-chromaFilter-01657 - if !potential_format_features.sampled_image_ycbcr_conversion_linear_filter { + if !potential_format_features + .intersects(FormatFeatures::SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER) + { return Err( SamplerYcbcrConversionCreationError::FormatLinearFilterNotSupported, ); @@ -727,8 +733,9 @@ impl Default for SamplerYcbcrConversionCreateInfo { } vulkan_enum! { - /// The conversion between the color model of the source image and the color model of the shader. #[non_exhaustive] + + /// The conversion between the color model of the source image and the color model of the shader. SamplerYcbcrModelConversion = SamplerYcbcrModelConversion(i32); /// The input values are already in the shader's model, and are passed through unmodified. @@ -751,8 +758,9 @@ vulkan_enum! { } vulkan_enum! { - /// How the numeric range of the input data is converted. #[non_exhaustive] + + /// How the numeric range of the input data is converted. SamplerYcbcrRange = SamplerYcbcrRange(i32); /// The input values cover the full numeric range, and are interpreted according to the ITU @@ -765,9 +773,10 @@ vulkan_enum! { } vulkan_enum! { + #[non_exhaustive] + /// For formats with chroma subsampling, the location where the chroma components are sampled, /// relative to the luma component. - #[non_exhaustive] ChromaLocation = ChromaLocation(i32); /// The chroma components are sampled at the even luma coordinate. diff --git a/vulkano/src/shader/mod.rs b/vulkano/src/shader/mod.rs index 144a1cd6..eada678f 100644 --- a/vulkano/src/shader/mod.rs +++ b/vulkano/src/shader/mod.rs @@ -22,7 +22,7 @@ use crate::{ device::{Device, DeviceOwned}, format::{Format, NumericType}, image::view::ImageViewType, - macros::{vulkan_bitflags, vulkan_enum}, + macros::vulkan_bitflags_enum, pipeline::{graphics::input_assembly::PrimitiveTopology, layout::PushConstantRange}, shader::spirv::{Capability, Spirv, SpirvError}, sync::PipelineStages, @@ -512,7 +512,7 @@ pub enum GeometryShaderInput { impl GeometryShaderInput { /// Returns true if the given primitive topology can be used as input for this geometry shader. #[inline] - pub fn is_compatible_with(&self, topology: PrimitiveTopology) -> bool { + pub fn is_compatible_with(self, topology: PrimitiveTopology) -> bool { match self { Self::Points => matches!(topology, PrimitiveTopology::PointList), Self::Lines => matches!( @@ -1056,72 +1056,88 @@ impl Display for ShaderInterfaceMismatchError { } } -vulkan_enum! { - /// A single shader stage. +vulkan_bitflags_enum! { #[non_exhaustive] - ShaderStage = ShaderStageFlags(u32); + + /// A set of [`ShaderStage`] values. + ShaderStages impl { + /// Creates a `ShaderStages` struct with all graphics stages set to `true`. + #[inline] + pub const fn all_graphics() -> ShaderStages { + ShaderStages::VERTEX + .union(ShaderStages::TESSELLATION_CONTROL) + .union(ShaderStages::TESSELLATION_EVALUATION) + .union(ShaderStages::GEOMETRY) + .union(ShaderStages::FRAGMENT) + } + }, + + /// A shader stage within a pipeline. + ShaderStage, + + = ShaderStageFlags(u32); // TODO: document - Vertex = VERTEX, + VERTEX, Vertex = VERTEX, // TODO: document - TessellationControl = TESSELLATION_CONTROL, + TESSELLATION_CONTROL, TessellationControl = TESSELLATION_CONTROL, // TODO: document - TessellationEvaluation = TESSELLATION_EVALUATION, + TESSELLATION_EVALUATION, TessellationEvaluation = TESSELLATION_EVALUATION, // TODO: document - Geometry = GEOMETRY, + GEOMETRY, Geometry = GEOMETRY, // TODO: document - Fragment = FRAGMENT, + FRAGMENT, Fragment = FRAGMENT, // TODO: document - Compute = COMPUTE, + COMPUTE, Compute = COMPUTE, // TODO: document - Raygen = RAYGEN_KHR { + RAYGEN, Raygen = RAYGEN_KHR { device_extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], }, // TODO: document - AnyHit = ANY_HIT_KHR { + ANY_HIT, AnyHit = ANY_HIT_KHR { device_extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], }, // TODO: document - ClosestHit = CLOSEST_HIT_KHR { + CLOSEST_HIT, ClosestHit = CLOSEST_HIT_KHR { device_extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], }, // TODO: document - Miss = MISS_KHR { + MISS, Miss = MISS_KHR { device_extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], }, // TODO: document - Intersection = INTERSECTION_KHR { + INTERSECTION, Intersection = INTERSECTION_KHR { device_extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], }, // TODO: document - Callable = CALLABLE_KHR { + CALLABLE, Callable = CALLABLE_KHR { device_extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], }, /* // TODO: document - Task = TASK_NV { + TASK, Task = TASK_NV { device_extensions: [nv_mesh_shader], }, // TODO: document - Mesh = MESH_NV { + MESH, Mesh = MESH_NV { device_extensions: [nv_mesh_shader], }, // TODO: document - SubpassShading = SUBPASS_SHADING_HUAWEI { + SUBPASS_SHADING, SubpassShading = SUBPASS_SHADING_HUAWEI { device_extensions: [huawei_subpass_shading], }, */ @@ -1147,186 +1163,47 @@ impl From for ShaderStage { } } -impl From for ShaderStages { - #[inline] - fn from(val: ShaderStage) -> Self { - match val { - ShaderStage::Vertex => Self { - vertex: true, - ..Self::empty() - }, - ShaderStage::TessellationControl => Self { - tessellation_control: true, - ..Self::empty() - }, - ShaderStage::TessellationEvaluation => Self { - tessellation_evaluation: true, - ..Self::empty() - }, - ShaderStage::Geometry => Self { - geometry: true, - ..Self::empty() - }, - ShaderStage::Fragment => Self { - fragment: true, - ..Self::empty() - }, - ShaderStage::Compute => Self { - compute: true, - ..Self::empty() - }, - ShaderStage::Raygen => Self { - raygen: true, - ..Self::empty() - }, - ShaderStage::AnyHit => Self { - any_hit: true, - ..Self::empty() - }, - ShaderStage::ClosestHit => Self { - closest_hit: true, - ..Self::empty() - }, - ShaderStage::Miss => Self { - miss: true, - ..Self::empty() - }, - ShaderStage::Intersection => Self { - intersection: true, - ..Self::empty() - }, - ShaderStage::Callable => Self { - callable: true, - ..Self::empty() - }, - } - } -} - -vulkan_bitflags! { - /// A set of shader stages. - #[non_exhaustive] - ShaderStages = ShaderStageFlags(u32); - - // TODO: document - vertex = VERTEX, - - // TODO: document - tessellation_control = TESSELLATION_CONTROL, - - // TODO: document - tessellation_evaluation = TESSELLATION_EVALUATION, - - // TODO: document - geometry = GEOMETRY, - - // TODO: document - fragment = FRAGMENT, - - // TODO: document - compute = COMPUTE, - - // TODO: document - raygen = RAYGEN_KHR { - device_extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], - }, - - // TODO: document - any_hit = ANY_HIT_KHR { - device_extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], - }, - - // TODO: document - closest_hit = CLOSEST_HIT_KHR { - device_extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], - }, - - // TODO: document - miss = MISS_KHR { - device_extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], - }, - - // TODO: document - intersection = INTERSECTION_KHR { - device_extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], - }, - - // TODO: document - callable = CALLABLE_KHR { - device_extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], - }, - - /* - // TODO: document - task = TASK_NV { - device_extensions: [nv_mesh_shader], - }, - - // TODO: document - mesh = MESH_NV { - device_extensions: [nv_mesh_shader], - }, - - // TODO: document - subpass_shading = SUBPASS_SHADING_HUAWEI { - device_extensions: [huawei_subpass_shading], - }, - */ -} - -impl ShaderStages { - /// Creates a `ShaderStages` struct with all graphics stages set to `true`. - #[inline] - pub const fn all_graphics() -> ShaderStages { - ShaderStages { - vertex: true, - tessellation_control: true, - tessellation_evaluation: true, - geometry: true, - fragment: true, - ..ShaderStages::empty() - } - } - - /// Creates a `ShaderStages` struct with the compute stage set to `true`. - #[inline] - pub const fn compute() -> ShaderStages { - ShaderStages { - compute: true, - ..ShaderStages::empty() - } - } -} - impl From for PipelineStages { #[inline] fn from(stages: ShaderStages) -> PipelineStages { - let ShaderStages { - vertex, - tessellation_control, - tessellation_evaluation, - geometry, - fragment, - compute, - raygen, - any_hit, - closest_hit, - miss, - intersection, - callable, - _ne: _, - } = stages; + let mut result = PipelineStages::empty(); - PipelineStages { - vertex_shader: vertex, - tessellation_control_shader: tessellation_control, - tessellation_evaluation_shader: tessellation_evaluation, - geometry_shader: geometry, - fragment_shader: fragment, - compute_shader: compute, - ray_tracing_shader: raygen | any_hit | closest_hit | miss | intersection | callable, - ..PipelineStages::empty() + if stages.intersects(ShaderStages::VERTEX) { + result |= PipelineStages::VERTEX_SHADER } + + if stages.intersects(ShaderStages::TESSELLATION_CONTROL) { + result |= PipelineStages::TESSELLATION_CONTROL_SHADER + } + + if stages.intersects(ShaderStages::TESSELLATION_EVALUATION) { + result |= PipelineStages::TESSELLATION_EVALUATION_SHADER + } + + if stages.intersects(ShaderStages::GEOMETRY) { + result |= PipelineStages::GEOMETRY_SHADER + } + + if stages.intersects(ShaderStages::FRAGMENT) { + result |= PipelineStages::FRAGMENT_SHADER + } + + if stages.intersects(ShaderStages::COMPUTE) { + result |= PipelineStages::COMPUTE_SHADER + } + + if stages.intersects( + ShaderStages::RAYGEN + | ShaderStages::ANY_HIT + | ShaderStages::CLOSEST_HIT + | ShaderStages::MISS + | ShaderStages::INTERSECTION + | ShaderStages::CALLABLE, + ) { + result |= PipelineStages::RAY_TRACING_SHADER + } + + result } } diff --git a/vulkano/src/shader/reflect.rs b/vulkano/src/shader/reflect.rs index e72359ba..21623bb6 100644 --- a/vulkano/src/shader/reflect.rs +++ b/vulkano/src/shader/reflect.rs @@ -65,7 +65,7 @@ pub fn entry_points( name, interface, .. - } => (execution_model, *entry_point, name, interface), + } => (*execution_model, *entry_point, name, interface), _ => return None, }; @@ -101,7 +101,7 @@ pub fn entry_points( Some(( entry_point_name.clone(), - *execution_model, + execution_model, EntryPointInfo { execution, descriptor_requirements, @@ -117,7 +117,7 @@ pub fn entry_points( /// Extracts the `ShaderExecution` for the entry point `function_id` from `spirv`. fn shader_execution( spirv: &Spirv, - execution_model: &ExecutionModel, + execution_model: ExecutionModel, function_id: Id, ) -> ShaderExecution { match execution_model { diff --git a/vulkano/src/swapchain/display.rs b/vulkano/src/swapchain/display.rs index 6cbb2e8a..09517bde 100644 --- a/vulkano/src/swapchain/display.rs +++ b/vulkano/src/swapchain/display.rs @@ -29,7 +29,7 @@ #![allow(unused_variables)] // TODO: this module isn't finished use crate::{ - device::physical::PhysicalDevice, swapchain::SupportedSurfaceTransforms, OomError, VulkanError, + device::physical::PhysicalDevice, swapchain::SurfaceTransforms, OomError, VulkanError, VulkanObject, }; use std::{ @@ -278,7 +278,7 @@ impl Display { /// Returns the transforms supported by this display. #[inline] - pub fn supported_transforms(&self) -> SupportedSurfaceTransforms { + pub fn supported_transforms(&self) -> SurfaceTransforms { self.properties.supported_transforms.into() } diff --git a/vulkano/src/swapchain/mod.rs b/vulkano/src/swapchain/mod.rs index 1b4504b5..90844660 100644 --- a/vulkano/src/swapchain/mod.rs +++ b/vulkano/src/swapchain/mod.rs @@ -189,12 +189,6 @@ //! # pre_transform: SurfaceTransform, composite_alpha: CompositeAlpha, //! # present_mode: PresentMode, full_screen_exclusive: FullScreenExclusive //! # ) -> Result<(), Box> { -//! // The created swapchain will be used as a color attachment for rendering. -//! let image_usage = ImageUsage { -//! color_attachment: true, -//! .. ImageUsage::empty() -//! }; -//! //! // Create the swapchain and its images. //! let (swapchain, images) = Swapchain::new( //! // Create the swapchain in this `device`'s memory. @@ -209,8 +203,8 @@ //! image_format: Some(image_format), //! // The size of each image. //! image_extent, -//! // What the images are going to be used for. -//! image_usage, +//! // The created swapchain images will be used as a color attachment for rendering. +//! image_usage: ImageUsage::COLOR_ATTACHMENT, //! // What transformation to use with the surface. //! pre_transform, //! // How to handle the alpha channel. @@ -329,9 +323,9 @@ pub use self::{ surface::{ - ColorSpace, CompositeAlpha, PresentMode, SupportedCompositeAlpha, - SupportedSurfaceTransforms, Surface, SurfaceApi, SurfaceCapabilities, SurfaceCreationError, - SurfaceInfo, SurfaceTransform, + ColorSpace, CompositeAlpha, CompositeAlphas, PresentMode, Surface, SurfaceApi, + SurfaceCapabilities, SurfaceCreationError, SurfaceInfo, SurfaceTransform, + SurfaceTransforms, }, swapchain::{ acquire_next_image, acquire_next_image_raw, present, wait_for_present, AcquireError, diff --git a/vulkano/src/swapchain/surface.rs b/vulkano/src/swapchain/surface.rs index 46582fa6..7f58bb1f 100644 --- a/vulkano/src/swapchain/surface.rs +++ b/vulkano/src/swapchain/surface.rs @@ -13,7 +13,7 @@ use crate::{ format::Format, image::ImageUsage, instance::Instance, - macros::{vulkan_bitflags, vulkan_enum}, + macros::{vulkan_bitflags_enum, vulkan_enum}, swapchain::{ display::{DisplayMode, DisplayPlane}, SurfaceSwapchainLock, @@ -104,7 +104,7 @@ impl Surface { fn validate_headless(instance: &Instance) -> Result<(), SurfaceCreationError> { if !instance.enabled_extensions().ext_headless_surface { return Err(SurfaceCreationError::RequirementNotMet { - required_for: "`headless`", + required_for: "`Surface::headless`", requires_one_of: RequiresOneOf { instance_extensions: &["ext_headless_surface"], ..Default::default() @@ -174,7 +174,7 @@ impl Surface { .khr_display { return Err(SurfaceCreationError::RequirementNotMet { - required_for: "`from_display_plane`", + required_for: "`Surface::from_display_plane`", requires_one_of: RequiresOneOf { instance_extensions: &["khr_display"], ..Default::default() @@ -259,7 +259,7 @@ impl Surface { ) -> Result<(), SurfaceCreationError> { if !instance.enabled_extensions().khr_android_surface { return Err(SurfaceCreationError::RequirementNotMet { - required_for: "`from_android`", + required_for: "`Surface::from_android`", requires_one_of: RequiresOneOf { instance_extensions: &["khr_android_surface"], ..Default::default() @@ -335,7 +335,7 @@ impl Surface { ) -> Result<(), SurfaceCreationError> { if !instance.enabled_extensions().ext_directfb_surface { return Err(SurfaceCreationError::RequirementNotMet { - required_for: "`from_directfb`", + required_for: "`Surface::from_directfb`", requires_one_of: RequiresOneOf { instance_extensions: &["ext_directfb_surface"], ..Default::default() @@ -415,7 +415,7 @@ impl Surface { ) -> Result<(), SurfaceCreationError> { if !instance.enabled_extensions().fuchsia_imagepipe_surface { return Err(SurfaceCreationError::RequirementNotMet { - required_for: "`from_fuchsia_image_pipe`", + required_for: "`Surface::from_fuchsia_image_pipe`", requires_one_of: RequiresOneOf { instance_extensions: &["fuchsia_imagepipe_surface"], ..Default::default() @@ -491,7 +491,7 @@ impl Surface { ) -> Result<(), SurfaceCreationError> { if !instance.enabled_extensions().ggp_stream_descriptor_surface { return Err(SurfaceCreationError::RequirementNotMet { - required_for: "`from_ggp_stream_descriptor`", + required_for: "`Surface::from_ggp_stream_descriptor`", requires_one_of: RequiresOneOf { instance_extensions: &["ggp_stream_descriptor_surface"], ..Default::default() @@ -566,7 +566,7 @@ impl Surface { ) -> Result<(), SurfaceCreationError> { if !instance.enabled_extensions().mvk_ios_surface { return Err(SurfaceCreationError::RequirementNotMet { - required_for: "`from_ios`", + required_for: "`Surface::from_ios`", requires_one_of: RequiresOneOf { instance_extensions: &["mvk_ios_surface"], ..Default::default() @@ -644,7 +644,7 @@ impl Surface { ) -> Result<(), SurfaceCreationError> { if !instance.enabled_extensions().mvk_macos_surface { return Err(SurfaceCreationError::RequirementNotMet { - required_for: "`from_mac_os`", + required_for: "`Surface::from_mac_os`", requires_one_of: RequiresOneOf { instance_extensions: &["mvk_macos_surface"], ..Default::default() @@ -719,7 +719,7 @@ impl Surface { ) -> Result<(), SurfaceCreationError> { if !instance.enabled_extensions().ext_metal_surface { return Err(SurfaceCreationError::RequirementNotMet { - required_for: "`from_metal`", + required_for: "`Surface::from_metal`", requires_one_of: RequiresOneOf { instance_extensions: &["ext_metal_surface"], ..Default::default() @@ -792,7 +792,7 @@ impl Surface { ) -> Result<(), SurfaceCreationError> { if !instance.enabled_extensions().qnx_screen_surface { return Err(SurfaceCreationError::RequirementNotMet { - required_for: "`from_qnx_screen`", + required_for: "`Surface::from_qnx_screen`", requires_one_of: RequiresOneOf { instance_extensions: &["qnx_screen_surface"], ..Default::default() @@ -868,7 +868,7 @@ impl Surface { ) -> Result<(), SurfaceCreationError> { if !instance.enabled_extensions().nn_vi_surface { return Err(SurfaceCreationError::RequirementNotMet { - required_for: "`from_vi`", + required_for: "`Surface::from_vi`", requires_one_of: RequiresOneOf { instance_extensions: &["nn_vi_surface"], ..Default::default() @@ -946,7 +946,7 @@ impl Surface { ) -> Result<(), SurfaceCreationError> { if !instance.enabled_extensions().khr_wayland_surface { return Err(SurfaceCreationError::RequirementNotMet { - required_for: "`from_wayland`", + required_for: "`Surface::from_wayland`", requires_one_of: RequiresOneOf { instance_extensions: &["khr_wayland_surface"], ..Default::default() @@ -1029,7 +1029,7 @@ impl Surface { ) -> Result<(), SurfaceCreationError> { if !instance.enabled_extensions().khr_win32_surface { return Err(SurfaceCreationError::RequirementNotMet { - required_for: "`from_win32`", + required_for: "`Surface::from_win32`", requires_one_of: RequiresOneOf { instance_extensions: &["khr_win32_surface"], ..Default::default() @@ -1112,7 +1112,7 @@ impl Surface { ) -> Result<(), SurfaceCreationError> { if !instance.enabled_extensions().khr_xcb_surface { return Err(SurfaceCreationError::RequirementNotMet { - required_for: "`from_xcb`", + required_for: "`Surface::from_xcb`", requires_one_of: RequiresOneOf { instance_extensions: &["khr_xcb_surface"], ..Default::default() @@ -1195,7 +1195,7 @@ impl Surface { ) -> Result<(), SurfaceCreationError> { if !instance.enabled_extensions().khr_xlib_surface { return Err(SurfaceCreationError::RequirementNotMet { - required_for: "`from_xlib`", + required_for: "`Surface::from_xlib`", requires_one_of: RequiresOneOf { instance_extensions: &["khr_xlib_surface"], ..Default::default() @@ -1416,6 +1416,8 @@ pub enum SurfaceApi { } vulkan_enum! { + #[non_exhaustive] + /// The mode of action when a swapchain image is presented. /// /// Swapchain images can be in one of three possible states: @@ -1435,7 +1437,6 @@ vulkan_enum! { /// [`surface_present_modes`] to see if they are supported. /// /// [`surface_present_modes`]: crate::device::physical::PhysicalDevice::surface_present_modes - #[non_exhaustive] PresentMode = PresentModeKHR(i32); /// The presentation engine holds only the currently displayed image. When presenting an image, @@ -1502,107 +1503,43 @@ vulkan_enum! { */ } -vulkan_enum! { - // TODO: document +vulkan_bitflags_enum! { #[non_exhaustive] - SurfaceTransform = SurfaceTransformFlagsKHR(u32); + + /// A set of [`SurfaceTransform`] values. + SurfaceTransforms, + + /// The presentation transform to apply when presenting a swapchain image to a surface. + SurfaceTransform, + + = SurfaceTransformFlagsKHR(u32); /// Don't transform the image. - Identity = IDENTITY, + IDENTITY, Identity = IDENTITY, /// Rotate 90 degrees. - Rotate90 = ROTATE_90, + ROTATE_90, Rotate90 = ROTATE_90, /// Rotate 180 degrees. - Rotate180 = ROTATE_180, + ROTATE_180, Rotate180 = ROTATE_180, /// Rotate 270 degrees. - Rotate270 = ROTATE_270, + ROTATE_270, Rotate270 = ROTATE_270, /// Mirror the image horizontally. - HorizontalMirror = HORIZONTAL_MIRROR, + HORIZONTAL_MIRROR, HorizontalMirror = HORIZONTAL_MIRROR, /// Mirror the image horizontally and rotate 90 degrees. - HorizontalMirrorRotate90 = HORIZONTAL_MIRROR_ROTATE_90, + HORIZONTAL_MIRROR_ROTATE_90, HorizontalMirrorRotate90 = HORIZONTAL_MIRROR_ROTATE_90, /// Mirror the image horizontally and rotate 180 degrees. - HorizontalMirrorRotate180 = HORIZONTAL_MIRROR_ROTATE_180, + HORIZONTAL_MIRROR_ROTATE_180, HorizontalMirrorRotate180 = HORIZONTAL_MIRROR_ROTATE_180, /// Mirror the image horizontally and rotate 270 degrees. - HorizontalMirrorRotate270 = HORIZONTAL_MIRROR_ROTATE_270, + HORIZONTAL_MIRROR_ROTATE_270, HorizontalMirrorRotate270 = HORIZONTAL_MIRROR_ROTATE_270, /// Let the operating system or driver implementation choose. - Inherit = INHERIT, -} - -vulkan_bitflags! { - /// List of supported composite alpha modes. - #[non_exhaustive] - SupportedSurfaceTransforms = SurfaceTransformFlagsKHR(u32); - - // TODO: document - identity = IDENTITY, - - // TODO: document - rotate90 = ROTATE_90, - - // TODO: document - rotate180 = ROTATE_180, - - // TODO: document - rotate270 = ROTATE_270, - - // TODO: document - horizontal_mirror = HORIZONTAL_MIRROR, - - // TODO: document - horizontal_mirror_rotate90 = HORIZONTAL_MIRROR_ROTATE_90, - - // TODO: document - horizontal_mirror_rotate180 = HORIZONTAL_MIRROR_ROTATE_180, - - // TODO: document - horizontal_mirror_rotate270 = HORIZONTAL_MIRROR_ROTATE_270, - - // TODO: document - inherit = INHERIT, -} - -impl SupportedSurfaceTransforms { - /// Returns true if the given `SurfaceTransform` is in this list. - #[inline] - pub fn supports(&self, value: SurfaceTransform) -> bool { - match value { - SurfaceTransform::Identity => self.identity, - SurfaceTransform::Rotate90 => self.rotate90, - SurfaceTransform::Rotate180 => self.rotate180, - SurfaceTransform::Rotate270 => self.rotate270, - SurfaceTransform::HorizontalMirror => self.horizontal_mirror, - SurfaceTransform::HorizontalMirrorRotate90 => self.horizontal_mirror_rotate90, - SurfaceTransform::HorizontalMirrorRotate180 => self.horizontal_mirror_rotate180, - SurfaceTransform::HorizontalMirrorRotate270 => self.horizontal_mirror_rotate270, - SurfaceTransform::Inherit => self.inherit, - } - } - - /// Returns an iterator to the list of supported composite alpha. - #[inline] - pub fn iter(&self) -> impl Iterator { - let moved = *self; - [ - SurfaceTransform::Identity, - SurfaceTransform::Rotate90, - SurfaceTransform::Rotate180, - SurfaceTransform::Rotate270, - SurfaceTransform::HorizontalMirror, - SurfaceTransform::HorizontalMirrorRotate90, - SurfaceTransform::HorizontalMirrorRotate180, - SurfaceTransform::HorizontalMirrorRotate270, - SurfaceTransform::Inherit, - ] - .into_iter() - .filter(move |&mode| moved.supports(mode)) - } + INHERIT, Inherit = INHERIT, } impl Default for SurfaceTransform { @@ -1612,75 +1549,36 @@ impl Default for SurfaceTransform { } } -vulkan_enum! { - /// How the alpha values of the pixels of the window are treated. +vulkan_bitflags_enum! { #[non_exhaustive] - CompositeAlpha = CompositeAlphaFlagsKHR(u32); + + /// A set of [`CompositeAlpha`] values. + CompositeAlphas, + + /// How the alpha values of the pixels of the window are treated. + CompositeAlpha, + + = CompositeAlphaFlagsKHR(u32); /// The alpha channel of the image is ignored. All the pixels are considered as if they have a /// value of 1.0. - Opaque = OPAQUE, + OPAQUE, Opaque = OPAQUE, /// The alpha channel of the image is respected. The color channels are expected to have /// already been multiplied by the alpha value. - PreMultiplied = PRE_MULTIPLIED, + PRE_MULTIPLIED, PreMultiplied = PRE_MULTIPLIED, /// The alpha channel of the image is respected. The color channels will be multiplied by the /// alpha value by the compositor before being added to what is behind. - PostMultiplied = POST_MULTIPLIED, + POST_MULTIPLIED, PostMultiplied = POST_MULTIPLIED, /// Let the operating system or driver implementation choose. - Inherit = INHERIT, -} - -vulkan_bitflags! { - /// List of supported composite alpha modes. - /// - /// See the docs of `CompositeAlpha`. - #[non_exhaustive] - SupportedCompositeAlpha = CompositeAlphaFlagsKHR(u32); - - // TODO: document - opaque = OPAQUE, - - // TODO: document - pre_multiplied = PRE_MULTIPLIED, - - // TODO: document - post_multiplied = POST_MULTIPLIED, - - // TODO: document - inherit = INHERIT, -} - -impl SupportedCompositeAlpha { - /// Returns true if the given `CompositeAlpha` is in this list. - #[inline] - pub fn supports(&self, value: CompositeAlpha) -> bool { - match value { - CompositeAlpha::Opaque => self.opaque, - CompositeAlpha::PreMultiplied => self.pre_multiplied, - CompositeAlpha::PostMultiplied => self.post_multiplied, - CompositeAlpha::Inherit => self.inherit, - } - } - - /// Returns an iterator to the list of supported composite alpha. - #[inline] - pub fn iter(&self) -> impl Iterator { - let moved = *self; - [ - CompositeAlpha::Opaque, - CompositeAlpha::PreMultiplied, - CompositeAlpha::PostMultiplied, - CompositeAlpha::Inherit, - ] - .into_iter() - .filter(move |&mode| moved.supports(mode)) - } + INHERIT, Inherit = INHERIT, } vulkan_enum! { + #[non_exhaustive] + /// How the presentation engine should interpret the data. /// /// # A quick lesson about color spaces @@ -1768,7 +1666,6 @@ vulkan_enum! { /// /// Additionally you can try detect whether the implementation supports any additional color /// space and perform a manual conversion to that color space from inside your shader. - #[non_exhaustive] ColorSpace = ColorSpaceKHR(i32); // TODO: document @@ -1933,13 +1830,13 @@ pub struct SurfaceCapabilities { pub max_image_array_layers: u32, /// List of transforms supported for the swapchain. - pub supported_transforms: SupportedSurfaceTransforms, + pub supported_transforms: SurfaceTransforms, /// Current transform used by the surface. pub current_transform: SurfaceTransform, /// List of composite alpha modes supports for the swapchain. - pub supported_composite_alpha: SupportedCompositeAlpha, + pub supported_composite_alpha: CompositeAlphas, /// List of image usages that are supported for images of the swapchain. Only /// the `color_attachment` usage is guaranteed to be supported. diff --git a/vulkano/src/swapchain/swapchain.rs b/vulkano/src/swapchain/swapchain.rs index 72a38c75..be02a386 100644 --- a/vulkano/src/swapchain/swapchain.rs +++ b/vulkano/src/swapchain/swapchain.rs @@ -8,8 +8,8 @@ // according to those terms. use super::{ - ColorSpace, CompositeAlpha, PresentMode, SupportedCompositeAlpha, SupportedSurfaceTransforms, - Surface, SurfaceTransform, SwapchainPresentInfo, + ColorSpace, CompositeAlpha, CompositeAlphas, PresentMode, Surface, SurfaceTransform, + SurfaceTransforms, SwapchainPresentInfo, }; use crate::{ buffer::sys::Buffer, @@ -295,7 +295,7 @@ impl Swapchain { if !device.enabled_extensions().khr_swapchain { return Err(SwapchainCreationError::RequirementNotMet { - required_for: "`Swapchain`", + required_for: "`Swapchain::new`", requires_one_of: RequiresOneOf { device_extensions: &["khr_swapchain"], ..Default::default() @@ -326,8 +326,8 @@ impl Swapchain { if full_screen_exclusive != FullScreenExclusive::Default { if !device.enabled_extensions().ext_full_screen_exclusive { return Err(SwapchainCreationError::RequirementNotMet { - required_for: - "`create_info.full_screen_exclusive` is not `FullScreenExclusive::Default`", + required_for: "`create_info.full_screen_exclusive` is not \ + `FullScreenExclusive::Default`", requires_one_of: RequiresOneOf { device_extensions: &["ext_full_screen_exclusive"], ..Default::default() @@ -506,7 +506,7 @@ impl Swapchain { // VUID-VkSwapchainCreateInfoKHR-preTransform-01279 if !surface_capabilities .supported_transforms - .supports(pre_transform) + .contains_enum(pre_transform) { return Err(SwapchainCreationError::PreTransformNotSupported { provided: pre_transform, @@ -517,7 +517,7 @@ impl Swapchain { // VUID-VkSwapchainCreateInfoKHR-compositeAlpha-01280 if !surface_capabilities .supported_composite_alpha - .supports(composite_alpha) + .contains_enum(composite_alpha) { return Err(SwapchainCreationError::CompositeAlphaNotSupported { provided: composite_alpha, @@ -1128,7 +1128,7 @@ pub enum SwapchainCreationError { /// The provided `composite_alpha` is not supported by the surface for this device. CompositeAlphaNotSupported { provided: CompositeAlpha, - supported: SupportedCompositeAlpha, + supported: CompositeAlphas, }, /// The provided `format` and `color_space` are not supported by the surface for this device. @@ -1185,7 +1185,7 @@ pub enum SwapchainCreationError { /// The provided `pre_transform` is not supported by the surface for this device. PreTransformNotSupported { provided: SurfaceTransform, - supported: SupportedSurfaceTransforms, + supported: SurfaceTransforms, }, /// The provided `surface` is not supported by any of the device's queue families. @@ -1340,8 +1340,9 @@ impl From for SwapchainCreationError { } vulkan_enum! { - /// The way full-screen exclusivity is handled. #[non_exhaustive] + + /// The way full-screen exclusivity is handled. FullScreenExclusive = FullScreenExclusiveEXT(i32); /// Indicates that the driver should determine the appropriate full-screen method diff --git a/vulkano/src/sync/fence.rs b/vulkano/src/sync/fence.rs index 5d93963f..de80aa06 100644 --- a/vulkano/src/sync/fence.rs +++ b/vulkano/src/sync/fence.rs @@ -9,7 +9,7 @@ use crate::{ device::{Device, DeviceOwned, Queue}, - macros::{vulkan_bitflags, vulkan_enum}, + macros::{vulkan_bitflags, vulkan_bitflags_enum}, OomError, RequirementNotMet, RequiresOneOf, Version, VulkanError, VulkanObject, }; use parking_lot::{Mutex, MutexGuard}; @@ -113,7 +113,7 @@ impl Fence { if !external_fence_properties .compatible_handle_types - .contains(&export_handle_types) + .contains(export_handle_types) { return Err(FenceError::ExportHandleTypesNotCompatible); } @@ -584,7 +584,7 @@ impl Fence { ) -> Result<(), FenceError> { if !self.device.enabled_extensions().khr_external_fence_fd { return Err(FenceError::RequirementNotMet { - required_for: "`export_fd`", + required_for: "`Fence::export_fd`", requires_one_of: RequiresOneOf { device_extensions: &["khr_external_fence_fd"], ..Default::default() @@ -596,7 +596,7 @@ impl Fence { handle_type.validate_device(&self.device)?; // VUID-VkFenceGetFdInfoKHR-handleType-01453 - if !self.export_handle_types.intersects(&handle_type.into()) { + if !self.export_handle_types.intersects(handle_type.into()) { return Err(FenceError::HandleTypeNotEnabled); } @@ -624,7 +624,7 @@ impl Fence { if !external_fence_properties .export_from_imported_handle_types - .intersects(&imported_handle_type.into()) + .intersects(imported_handle_type.into()) { return Err(FenceError::ExportFromImportedNotSupported { imported_handle_type, @@ -709,7 +709,7 @@ impl Fence { ) -> Result<(), FenceError> { if !self.device.enabled_extensions().khr_external_fence_win32 { return Err(FenceError::RequirementNotMet { - required_for: "`export_win32_handle`", + required_for: "`Fence::export_win32_handle`", requires_one_of: RequiresOneOf { device_extensions: &["khr_external_fence_win32"], ..Default::default() @@ -721,7 +721,7 @@ impl Fence { handle_type.validate_device(&self.device)?; // VUID-VkFenceGetWin32HandleInfoKHR-handleType-01448 - if !self.export_handle_types.intersects(&handle_type.into()) { + if !self.export_handle_types.intersects(handle_type.into()) { return Err(FenceError::HandleTypeNotEnabled); } @@ -756,7 +756,7 @@ impl Fence { if !external_fence_properties .export_from_imported_handle_types - .intersects(&imported_handle_type.into()) + .intersects(imported_handle_type.into()) { return Err(FenceError::ExportFromImportedNotSupported { imported_handle_type, @@ -845,7 +845,7 @@ impl Fence { ) -> Result<(), FenceError> { if !self.device.enabled_extensions().khr_external_fence_fd { return Err(FenceError::RequirementNotMet { - required_for: "`import_fd`", + required_for: "`Fence::import_fd`", requires_one_of: RequiresOneOf { device_extensions: &["khr_external_fence_fd"], ..Default::default() @@ -883,7 +883,7 @@ impl Fence { // Can't validate, therefore unsafe // VUID-VkImportFenceFdInfoKHR-handleType-07306 - if handle_type.has_copy_transference() && !flags.temporary { + if handle_type.has_copy_transference() && !flags.intersects(FenceImportFlags::TEMPORARY) { return Err(FenceError::HandletypeCopyNotTemporary); } @@ -929,7 +929,7 @@ impl Fence { .result() .map_err(VulkanError::from)?; - state.import(handle_type, flags.temporary); + state.import(handle_type, flags.intersects(FenceImportFlags::TEMPORARY)); Ok(()) } @@ -964,7 +964,7 @@ impl Fence { ) -> Result<(), FenceError> { if !self.device.enabled_extensions().khr_external_fence_win32 { return Err(FenceError::RequirementNotMet { - required_for: "`import_win32_handle`", + required_for: "`Fence::import_win32_handle`", requires_one_of: RequiresOneOf { device_extensions: &["khr_external_fence_win32"], ..Default::default() @@ -1002,7 +1002,7 @@ impl Fence { // Can't validate, therefore unsafe // VUID? - if handle_type.has_copy_transference() && !flags.temporary { + if handle_type.has_copy_transference() && !flags.intersects(FenceImportFlags::TEMPORARY) { return Err(FenceError::HandletypeCopyNotTemporary); } @@ -1050,7 +1050,7 @@ impl Fence { .result() .map_err(VulkanError::from)?; - state.import(handle_type, flags.temporary); + state.import(handle_type, flags.intersects(FenceImportFlags::TEMPORARY)); Ok(()) } @@ -1160,7 +1160,7 @@ impl FenceState { #[allow(dead_code)] #[inline] fn is_exported(&self, handle_type: ExternalFenceHandleType) -> bool { - self.exported_handle_types.intersects(&handle_type.into()) + self.exported_handle_types.intersects(handle_type.into()) } #[inline] @@ -1265,119 +1265,60 @@ impl Default for FenceCreateInfo { } } -vulkan_enum! { - /// The handle type used for Vulkan external fence APIs. +vulkan_bitflags_enum! { #[non_exhaustive] - ExternalFenceHandleType = ExternalFenceHandleTypeFlags(u32); + /// A set of [`ExternalFenceHandleType`] values. + ExternalFenceHandleTypes, - /// A POSIX file descriptor handle that is only usable with Vulkan and compatible APIs. - /// - /// This handle type has *reference transference*. - OpaqueFd = OPAQUE_FD, - - /// A Windows NT handle that is only usable with Vulkan and compatible APIs. - /// - /// This handle type has *reference transference*. - OpaqueWin32 = OPAQUE_WIN32, - - /// A Windows global share handle that is only usable with Vulkan and compatible APIs. - /// - /// This handle type has *reference transference*. - OpaqueWin32Kmt = OPAQUE_WIN32_KMT, - - /// A POSIX file descriptor handle to a Linux Sync File or Android Fence object. - /// - /// This handle type has *copy transference*. - SyncFd = SYNC_FD, -} - -impl ExternalFenceHandleType { - /// Returns whether the given handle type has *copy transference* rather than *reference - /// transference*. - /// - /// Imports of handles with copy transference must always be temporary. Exports of such - /// handles must only occur if the fence is already signaled, or if there is a fence signal - /// operation pending in a queue. - #[inline] - pub fn has_copy_transference(&self) -> bool { - // As defined by - // https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap7.html#synchronization-fence-handletypes-win32 - // https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap7.html#synchronization-fence-handletypes-fd - matches!(self, Self::SyncFd) - } -} - -vulkan_bitflags! { - /// A mask of multiple external fence handle types. - #[non_exhaustive] - ExternalFenceHandleTypes = ExternalFenceHandleTypeFlags(u32); - - /// A POSIX file descriptor handle that is only usable with Vulkan and compatible APIs. - /// - /// This handle type has *reference transference*. - opaque_fd = OPAQUE_FD, - - /// A Windows NT handle that is only usable with Vulkan and compatible APIs. - /// - /// This handle type has *reference transference*. - opaque_win32 = OPAQUE_WIN32, - - /// A Windows global share handle that is only usable with Vulkan and compatible APIs. - /// - /// This handle type has *reference transference*. - opaque_win32_kmt = OPAQUE_WIN32_KMT, - - /// A POSIX file descriptor handle to a Linux Sync File or Android Fence object. - /// - /// This handle type has *copy transference*. - sync_fd = SYNC_FD, -} - -impl From for ExternalFenceHandleTypes { - #[inline] - fn from(val: ExternalFenceHandleType) -> Self { - let mut result = Self::empty(); - - match val { - ExternalFenceHandleType::OpaqueFd => result.opaque_fd = true, - ExternalFenceHandleType::OpaqueWin32 => result.opaque_win32 = true, - ExternalFenceHandleType::OpaqueWin32Kmt => result.opaque_win32_kmt = true, - ExternalFenceHandleType::SyncFd => result.sync_fd = true, + /// The handle type used to export or import fences to/from an external source. + ExternalFenceHandleType impl { + /// Returns whether the given handle type has *copy transference* rather than *reference + /// transference*. + /// + /// Imports of handles with copy transference must always be temporary. Exports of such + /// handles must only occur if the fence is already signaled, or if there is a fence signal + /// operation pending in a queue. + #[inline] + pub fn has_copy_transference(self) -> bool { + // As defined by + // https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap7.html#synchronization-fence-handletypes-win32 + // https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap7.html#synchronization-fence-handletypes-fd + matches!(self, Self::SyncFd) } + }, - result - } -} + = ExternalFenceHandleTypeFlags(u32); -impl ExternalFenceHandleTypes { - fn into_iter(self) -> impl IntoIterator { - let Self { - opaque_fd, - opaque_win32, - opaque_win32_kmt, - sync_fd, - _ne: _, - } = self; + /// A POSIX file descriptor handle that is only usable with Vulkan and compatible APIs. + /// + /// This handle type has *reference transference*. + OPAQUE_FD, OpaqueFd = OPAQUE_FD, - [ - opaque_fd.then_some(ExternalFenceHandleType::OpaqueFd), - opaque_win32.then_some(ExternalFenceHandleType::OpaqueWin32), - opaque_win32_kmt.then_some(ExternalFenceHandleType::OpaqueWin32Kmt), - sync_fd.then_some(ExternalFenceHandleType::SyncFd), - ] - .into_iter() - .flatten() - } + /// A Windows NT handle that is only usable with Vulkan and compatible APIs. + /// + /// This handle type has *reference transference*. + OPAQUE_WIN32, OpaqueWin32 = OPAQUE_WIN32, + + /// A Windows global share handle that is only usable with Vulkan and compatible APIs. + /// + /// This handle type has *reference transference*. + OPAQUE_WIN32_KMT, OpaqueWin32Kmt = OPAQUE_WIN32_KMT, + + /// A POSIX file descriptor handle to a Linux Sync File or Android Fence object. + /// + /// This handle type has *copy transference*. + SYNC_FD, SyncFd = SYNC_FD, } vulkan_bitflags! { - /// Additional parameters for a fence payload import. #[non_exhaustive] + + /// Additional parameters for a fence payload import. FenceImportFlags = FenceImportFlags(u32); /// The fence payload will be imported only temporarily, regardless of the permanence of the /// imported handle type. - temporary = TEMPORARY, + TEMPORARY = TEMPORARY, } #[cfg(unix)] diff --git a/vulkano/src/sync/future/fence_signal.rs b/vulkano/src/sync/future/fence_signal.rs index 49a20b02..99852bfe 100644 --- a/vulkano/src/sync/future/fence_signal.rs +++ b/vulkano/src/sync/future/fence_signal.rs @@ -11,7 +11,7 @@ use super::{AccessCheckError, FlushError, GpuFuture}; use crate::{ buffer::sys::Buffer, command_buffer::{SemaphoreSubmitInfo, SubmitInfo}, - device::{Device, DeviceOwned, Queue}, + device::{Device, DeviceOwned, Queue, QueueFlags}, image::{sys::Image, ImageLayout}, swapchain::Swapchain, sync::{AccessError, AccessFlags, Fence, PipelineStages, SubmitAnyBuilder}, @@ -258,11 +258,8 @@ where .into_iter() .map(|semaphore| { SemaphoreSubmitInfo { - stages: PipelineStages { - // TODO: correct stages ; hard - all_commands: true, - ..PipelineStages::empty() - }, + // TODO: correct stages ; hard + stages: PipelineStages::ALL_COMMANDS, ..SemaphoreSubmitInfo::semaphore(semaphore) } }) @@ -298,12 +295,10 @@ where debug_assert!(!partially_flushed); // Same remark as `CommandBuffer`. assert!(fence.is_none()); - debug_assert!( - queue.device().physical_device().queue_family_properties() - [queue.queue_family_index() as usize] - .queue_flags - .sparse_binding - ); + debug_assert!(queue.device().physical_device().queue_family_properties() + [queue.queue_family_index() as usize] + .queue_flags + .intersects(QueueFlags::SPARSE_BINDING)); queue .with(|mut q| q.bind_sparse_unchecked(bind_infos, Some(new_fence.clone()))) diff --git a/vulkano/src/sync/future/semaphore_signal.rs b/vulkano/src/sync/future/semaphore_signal.rs index 7960ec1a..3b9e9e0c 100644 --- a/vulkano/src/sync/future/semaphore_signal.rs +++ b/vulkano/src/sync/future/semaphore_signal.rs @@ -108,11 +108,8 @@ where .into_iter() .map(|semaphore| { SemaphoreSubmitInfo { - stages: PipelineStages { - // TODO: correct stages ; hard - all_commands: true, - ..PipelineStages::empty() - }, + // TODO: correct stages ; hard + stages: PipelineStages::ALL_COMMANDS, ..SemaphoreSubmitInfo::semaphore(semaphore) } }) diff --git a/vulkano/src/sync/pipeline.rs b/vulkano/src/sync/pipeline.rs index cc4a57b2..bd262461 100644 --- a/vulkano/src/sync/pipeline.rs +++ b/vulkano/src/sync/pipeline.rs @@ -9,23 +9,428 @@ use crate::{ buffer::sys::Buffer, + device::QueueFlags, image::{sys::Image, ImageAspects, ImageLayout, ImageSubresourceRange}, - macros::{vulkan_bitflags, vulkan_enum}, + macros::{vulkan_bitflags, vulkan_bitflags_enum}, DeviceSize, }; use smallvec::SmallVec; use std::{ops::Range, sync::Arc}; -vulkan_enum! { - /// A single stage in the device's processing pipeline. +vulkan_bitflags_enum! { #[non_exhaustive] - PipelineStage = PipelineStageFlags2(u64); + /// A set of [`PipelineStage`] values. + PipelineStages impl { + /// Returns whether `self` contains stages that are only available in + /// `VkPipelineStageFlagBits2`. + pub(crate) fn is_2(self) -> bool { + !(self + - (PipelineStages::TOP_OF_PIPE + | PipelineStages::DRAW_INDIRECT + | PipelineStages::VERTEX_INPUT + | PipelineStages::VERTEX_SHADER + | PipelineStages::TESSELLATION_CONTROL_SHADER + | PipelineStages::TESSELLATION_EVALUATION_SHADER + | PipelineStages::GEOMETRY_SHADER + | PipelineStages::FRAGMENT_SHADER + | PipelineStages::EARLY_FRAGMENT_TESTS + | PipelineStages::LATE_FRAGMENT_TESTS + | PipelineStages::COLOR_ATTACHMENT_OUTPUT + | PipelineStages::COMPUTE_SHADER + | PipelineStages::ALL_TRANSFER + | PipelineStages::BOTTOM_OF_PIPE + | PipelineStages::HOST + | PipelineStages::ALL_GRAPHICS + | PipelineStages::ALL_COMMANDS + | PipelineStages::TRANSFORM_FEEDBACK + | PipelineStages::CONDITIONAL_RENDERING + | PipelineStages::ACCELERATION_STRUCTURE_BUILD + | PipelineStages::RAY_TRACING_SHADER + | PipelineStages::FRAGMENT_DENSITY_PROCESS + | PipelineStages::FRAGMENT_SHADING_RATE_ATTACHMENT + | PipelineStages::COMMAND_PREPROCESS + | PipelineStages::TASK_SHADER + | PipelineStages::MESH_SHADER)) + .is_empty() + } + + /// Replaces and unsets flags that are equivalent to multiple other flags. + /// + /// This may set flags that are not supported by the device, so this is for internal use only + /// and should not be passed on to Vulkan. + pub(crate) fn normalize(mut self) -> Self { + if self.intersects(PipelineStages::ALL_COMMANDS) { + self -= PipelineStages::ALL_COMMANDS; + self |= PipelineStages::TOP_OF_PIPE + | PipelineStages::DRAW_INDIRECT + | PipelineStages::VERTEX_INPUT + | PipelineStages::VERTEX_SHADER + | PipelineStages::TESSELLATION_CONTROL_SHADER + | PipelineStages::TESSELLATION_EVALUATION_SHADER + | PipelineStages::GEOMETRY_SHADER + | PipelineStages::FRAGMENT_SHADER + | PipelineStages::EARLY_FRAGMENT_TESTS + | PipelineStages::LATE_FRAGMENT_TESTS + | PipelineStages::COLOR_ATTACHMENT_OUTPUT + | PipelineStages::COMPUTE_SHADER + | PipelineStages::ALL_TRANSFER + | PipelineStages::BOTTOM_OF_PIPE + | PipelineStages::HOST + | PipelineStages::ALL_GRAPHICS + | PipelineStages::COPY + | PipelineStages::RESOLVE + | PipelineStages::BLIT + | PipelineStages::CLEAR + | PipelineStages::INDEX_INPUT + | PipelineStages::VERTEX_ATTRIBUTE_INPUT + | PipelineStages::PRE_RASTERIZATION_SHADERS + | PipelineStages::VIDEO_DECODE + | PipelineStages::VIDEO_ENCODE + | PipelineStages::TRANSFORM_FEEDBACK + | PipelineStages::CONDITIONAL_RENDERING + | PipelineStages::ACCELERATION_STRUCTURE_BUILD + | PipelineStages::RAY_TRACING_SHADER + | PipelineStages::FRAGMENT_DENSITY_PROCESS + | PipelineStages::FRAGMENT_SHADING_RATE_ATTACHMENT + | PipelineStages::COMMAND_PREPROCESS + | PipelineStages::TASK_SHADER + | PipelineStages::MESH_SHADER + | PipelineStages::SUBPASS_SHADING + | PipelineStages::INVOCATION_MASK; + } + + if self.intersects(PipelineStages::ALL_GRAPHICS) { + self -= PipelineStages::ALL_GRAPHICS; + self |= PipelineStages::DRAW_INDIRECT + | PipelineStages::TASK_SHADER + | PipelineStages::MESH_SHADER + | PipelineStages::VERTEX_INPUT + | PipelineStages::VERTEX_SHADER + | PipelineStages::TESSELLATION_CONTROL_SHADER + | PipelineStages::TESSELLATION_EVALUATION_SHADER + | PipelineStages::GEOMETRY_SHADER + | PipelineStages::FRAGMENT_SHADER + | PipelineStages::EARLY_FRAGMENT_TESTS + | PipelineStages::LATE_FRAGMENT_TESTS + | PipelineStages::COLOR_ATTACHMENT_OUTPUT + | PipelineStages::TRANSFORM_FEEDBACK + | PipelineStages::CONDITIONAL_RENDERING + | PipelineStages::FRAGMENT_SHADING_RATE_ATTACHMENT + | PipelineStages::FRAGMENT_DENSITY_PROCESS + | PipelineStages::INVOCATION_MASK; + } + + if self.intersects(PipelineStages::VERTEX_INPUT) { + self -= PipelineStages::VERTEX_INPUT; + self |= PipelineStages::INDEX_INPUT | PipelineStages::VERTEX_ATTRIBUTE_INPUT; + } + + if self.intersects(PipelineStages::PRE_RASTERIZATION_SHADERS) { + self -= PipelineStages::PRE_RASTERIZATION_SHADERS; + self |= PipelineStages::VERTEX_SHADER + | PipelineStages::TESSELLATION_CONTROL_SHADER + | PipelineStages::TESSELLATION_EVALUATION_SHADER + | PipelineStages::GEOMETRY_SHADER + | PipelineStages::TASK_SHADER + | PipelineStages::MESH_SHADER; + } + + if self.intersects(PipelineStages::ALL_TRANSFER) { + self -= PipelineStages::ALL_TRANSFER; + self |= PipelineStages::COPY + | PipelineStages::RESOLVE + | PipelineStages::BLIT + | PipelineStages::CLEAR; + //PipelineStages::ACCELERATION_STRUCTURE_COPY; + } + + self + } + + /// Returns the access types that are supported with the given pipeline stages. + /// + /// Corresponds to the table + /// "[Supported access types](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap7.html#synchronization-access-types-supported)" + /// in the Vulkan specification. + #[inline] + pub fn supported_access(mut self) -> AccessFlags { + if self.is_empty() { + return AccessFlags::empty(); + } + + self = self.normalize(); + let mut result = AccessFlags::MEMORY_READ | AccessFlags::MEMORY_WRITE; + + if self.intersects(PipelineStages::DRAW_INDIRECT) { + result |= + AccessFlags::INDIRECT_COMMAND_READ | AccessFlags::TRANSFORM_FEEDBACK_COUNTER_READ; + } + + if self.intersects(PipelineStages::VERTEX_INPUT) {} + + if self.intersects(PipelineStages::VERTEX_SHADER) { + result |= AccessFlags::SHADER_READ + | AccessFlags::UNIFORM_READ + | AccessFlags::SHADER_SAMPLED_READ + | AccessFlags::SHADER_STORAGE_READ + | AccessFlags::SHADER_WRITE + | AccessFlags::SHADER_STORAGE_WRITE + | AccessFlags::ACCELERATION_STRUCTURE_READ; + } + + if self.intersects(PipelineStages::TESSELLATION_CONTROL_SHADER) { + result |= AccessFlags::SHADER_READ + | AccessFlags::UNIFORM_READ + | AccessFlags::SHADER_SAMPLED_READ + | AccessFlags::SHADER_STORAGE_READ + | AccessFlags::SHADER_WRITE + | AccessFlags::SHADER_STORAGE_WRITE + | AccessFlags::ACCELERATION_STRUCTURE_READ; + } + + if self.intersects(PipelineStages::TESSELLATION_EVALUATION_SHADER) { + result |= AccessFlags::SHADER_READ + | AccessFlags::UNIFORM_READ + | AccessFlags::SHADER_SAMPLED_READ + | AccessFlags::SHADER_STORAGE_READ + | AccessFlags::SHADER_WRITE + | AccessFlags::SHADER_STORAGE_WRITE + | AccessFlags::ACCELERATION_STRUCTURE_READ; + } + + if self.intersects(PipelineStages::GEOMETRY_SHADER) { + result |= AccessFlags::SHADER_READ + | AccessFlags::UNIFORM_READ + | AccessFlags::SHADER_SAMPLED_READ + | AccessFlags::SHADER_STORAGE_READ + | AccessFlags::SHADER_WRITE + | AccessFlags::SHADER_STORAGE_WRITE + | AccessFlags::ACCELERATION_STRUCTURE_READ; + } + + if self.intersects(PipelineStages::FRAGMENT_SHADER) { + result |= AccessFlags::SHADER_READ + | AccessFlags::UNIFORM_READ + | AccessFlags::SHADER_SAMPLED_READ + | AccessFlags::SHADER_STORAGE_READ + | AccessFlags::SHADER_WRITE + | AccessFlags::SHADER_STORAGE_WRITE + | AccessFlags::ACCELERATION_STRUCTURE_READ + | AccessFlags::INPUT_ATTACHMENT_READ; + } + + if self.intersects(PipelineStages::EARLY_FRAGMENT_TESTS) { + result |= AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ + | AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE; + } + + if self.intersects(PipelineStages::LATE_FRAGMENT_TESTS) { + result |= AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ + | AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE; + } + + if self.intersects(PipelineStages::COLOR_ATTACHMENT_OUTPUT) { + result |= AccessFlags::COLOR_ATTACHMENT_READ + | AccessFlags::COLOR_ATTACHMENT_WRITE + | AccessFlags::COLOR_ATTACHMENT_READ_NONCOHERENT; + } + + if self.intersects(PipelineStages::COMPUTE_SHADER) { + result |= AccessFlags::SHADER_READ + | AccessFlags::UNIFORM_READ + | AccessFlags::SHADER_SAMPLED_READ + | AccessFlags::SHADER_STORAGE_READ + | AccessFlags::SHADER_WRITE + | AccessFlags::SHADER_STORAGE_WRITE + | AccessFlags::ACCELERATION_STRUCTURE_READ; + } + + if self.intersects(PipelineStages::ALL_TRANSFER) {} + + if self.intersects(PipelineStages::BOTTOM_OF_PIPE) {} + + if self.intersects(PipelineStages::HOST) { + result |= AccessFlags::HOST_READ | AccessFlags::HOST_WRITE; + } + + if self.intersects(PipelineStages::ALL_GRAPHICS) {} + + if self.intersects(PipelineStages::ALL_COMMANDS) {} + + if self.intersects(PipelineStages::COPY) { + result |= AccessFlags::TRANSFER_READ | AccessFlags::TRANSFER_WRITE; + } + + if self.intersects(PipelineStages::RESOLVE) { + result |= AccessFlags::TRANSFER_READ | AccessFlags::TRANSFER_WRITE; + } + + if self.intersects(PipelineStages::BLIT) { + result |= AccessFlags::TRANSFER_READ | AccessFlags::TRANSFER_WRITE; + } + + if self.intersects(PipelineStages::CLEAR) { + result |= AccessFlags::TRANSFER_WRITE; + } + + if self.intersects(PipelineStages::INDEX_INPUT) { + result |= AccessFlags::INDEX_READ; + } + + if self.intersects(PipelineStages::VERTEX_ATTRIBUTE_INPUT) { + result |= AccessFlags::VERTEX_ATTRIBUTE_READ; + } + + if self.intersects(PipelineStages::PRE_RASTERIZATION_SHADERS) {} + + if self.intersects(PipelineStages::VIDEO_DECODE) { + result |= AccessFlags::VIDEO_DECODE_READ | AccessFlags::VIDEO_DECODE_WRITE; + } + + if self.intersects(PipelineStages::VIDEO_ENCODE) { + result |= AccessFlags::VIDEO_ENCODE_READ | AccessFlags::VIDEO_ENCODE_WRITE; + } + + if self.intersects(PipelineStages::TRANSFORM_FEEDBACK) { + result |= AccessFlags::TRANSFORM_FEEDBACK_WRITE + | AccessFlags::TRANSFORM_FEEDBACK_COUNTER_WRITE + | AccessFlags::TRANSFORM_FEEDBACK_COUNTER_READ; + } + + if self.intersects(PipelineStages::CONDITIONAL_RENDERING) { + result |= AccessFlags::CONDITIONAL_RENDERING_READ; + } + + if self.intersects(PipelineStages::ACCELERATION_STRUCTURE_BUILD) { + result |= AccessFlags::INDIRECT_COMMAND_READ + | AccessFlags::SHADER_READ + | AccessFlags::SHADER_SAMPLED_READ + | AccessFlags::SHADER_STORAGE_READ + | AccessFlags::SHADER_STORAGE_WRITE + | AccessFlags::TRANSFER_READ + | AccessFlags::TRANSFER_WRITE + | AccessFlags::ACCELERATION_STRUCTURE_READ + | AccessFlags::ACCELERATION_STRUCTURE_WRITE; + } + + if self.intersects(PipelineStages::RAY_TRACING_SHADER) { + result |= AccessFlags::SHADER_READ + | AccessFlags::UNIFORM_READ + | AccessFlags::SHADER_SAMPLED_READ + | AccessFlags::SHADER_STORAGE_READ + | AccessFlags::SHADER_WRITE + | AccessFlags::SHADER_STORAGE_WRITE + | AccessFlags::ACCELERATION_STRUCTURE_READ; + } + + if self.intersects(PipelineStages::FRAGMENT_DENSITY_PROCESS) { + result |= AccessFlags::FRAGMENT_DENSITY_MAP_READ; + } + + if self.intersects(PipelineStages::FRAGMENT_SHADING_RATE_ATTACHMENT) { + result |= AccessFlags::FRAGMENT_SHADING_RATE_ATTACHMENT_READ; + } + + if self.intersects(PipelineStages::COMMAND_PREPROCESS) { + result |= AccessFlags::COMMAND_PREPROCESS_READ | AccessFlags::COMMAND_PREPROCESS_WRITE; + } + + if self.intersects(PipelineStages::TASK_SHADER) { + result |= AccessFlags::SHADER_READ + | AccessFlags::UNIFORM_READ + | AccessFlags::SHADER_SAMPLED_READ + | AccessFlags::SHADER_STORAGE_READ + | AccessFlags::SHADER_WRITE + | AccessFlags::SHADER_STORAGE_WRITE + | AccessFlags::ACCELERATION_STRUCTURE_READ; + } + + if self.intersects(PipelineStages::MESH_SHADER) { + result |= AccessFlags::SHADER_READ + | AccessFlags::UNIFORM_READ + | AccessFlags::SHADER_SAMPLED_READ + | AccessFlags::SHADER_STORAGE_READ + | AccessFlags::SHADER_WRITE + | AccessFlags::SHADER_STORAGE_WRITE + | AccessFlags::ACCELERATION_STRUCTURE_READ; + } + + if self.intersects(PipelineStages::SUBPASS_SHADING) { + result |= AccessFlags::INPUT_ATTACHMENT_READ; + } + + if self.intersects(PipelineStages::INVOCATION_MASK) { + result |= AccessFlags::INVOCATION_MASK_READ; + } + + result + } + }, + + /// A single stage in the device's processing pipeline. + PipelineStage impl { + #[inline] + pub fn required_queue_flags(self) -> QueueFlags { + // https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap7.html#synchronization-pipeline-stages-supported + match self { + Self::TopOfPipe => QueueFlags::empty(), + Self::DrawIndirect => QueueFlags::GRAPHICS | QueueFlags::COMPUTE, + Self::VertexInput => QueueFlags::GRAPHICS, + Self::VertexShader => QueueFlags::GRAPHICS, + Self::TessellationControlShader => QueueFlags::GRAPHICS, + Self::TessellationEvaluationShader => QueueFlags::GRAPHICS, + Self::GeometryShader => QueueFlags::GRAPHICS, + Self::FragmentShader => QueueFlags::GRAPHICS, + Self::EarlyFragmentTests => QueueFlags::GRAPHICS, + Self::LateFragmentTests => QueueFlags::GRAPHICS, + Self::ColorAttachmentOutput => QueueFlags::GRAPHICS, + Self::ComputeShader => QueueFlags::COMPUTE, + Self::AllTransfer => QueueFlags::GRAPHICS | QueueFlags::COMPUTE | QueueFlags::TRANSFER, + Self::BottomOfPipe => QueueFlags::empty(), + Self::Host => QueueFlags::empty(), + Self::AllGraphics => QueueFlags::GRAPHICS, + Self::AllCommands => QueueFlags::empty(), + Self::Copy => todo!( + "The spec doesn't currently say which queue flags support this pipeline stage" + ), + Self::Resolve => todo!( + "The spec doesn't currently say which queue flags support this pipeline stage" + ), + Self::Blit => todo!( + "The spec doesn't currently say which queue flags support this pipeline stage" + ), + Self::Clear => todo!( + "The spec doesn't currently say which queue flags support this pipeline stage" + ), + Self::IndexInput => QueueFlags::GRAPHICS, + Self::VertexAttributeInput => QueueFlags::GRAPHICS, + Self::PreRasterizationShaders => QueueFlags::GRAPHICS, + Self::VideoDecode => QueueFlags::VIDEO_DECODE, + Self::VideoEncode => QueueFlags::VIDEO_ENCODE, + Self::ConditionalRendering => QueueFlags::GRAPHICS | QueueFlags::COMPUTE, + Self::TransformFeedback => QueueFlags::GRAPHICS, + Self::CommandPreprocess => QueueFlags::GRAPHICS | QueueFlags::COMPUTE, + Self::FragmentShadingRateAttachment => QueueFlags::GRAPHICS, + Self::TaskShader => QueueFlags::GRAPHICS, + Self::MeshShader => QueueFlags::GRAPHICS, + Self::AccelerationStructureBuild => QueueFlags::COMPUTE, + Self::RayTracingShader => QueueFlags::COMPUTE, + Self::FragmentDensityProcess => QueueFlags::GRAPHICS, + Self::SubpassShading => QueueFlags::GRAPHICS, + Self::InvocationMask => todo!( + "The spec doesn't currently say which queue flags support this pipeline stage" + ), + } + } + }, + + = PipelineStageFlags2(u64); /// A pseudo-stage representing the start of the pipeline. - TopOfPipe = TOP_OF_PIPE, + TOP_OF_PIPE, TopOfPipe = TOP_OF_PIPE, /// Indirect buffers are read. - DrawIndirect = DRAW_INDIRECT, + DRAW_INDIRECT, DrawIndirect = DRAW_INDIRECT, /// Vertex and index buffers are read. /// @@ -34,40 +439,40 @@ vulkan_enum! { /// flags that are added to Vulkan, if they are not yet supported by Vulkano. /// - `index_input` /// - `vertex_attribute_input` - VertexInput = VERTEX_INPUT, + VERTEX_INPUT, VertexInput = VERTEX_INPUT, /// Vertex shaders are executed. - VertexShader = VERTEX_SHADER, + VERTEX_SHADER, VertexShader = VERTEX_SHADER, /// Tessellation control shaders are executed. - TessellationControlShader = TESSELLATION_CONTROL_SHADER, + TESSELLATION_CONTROL_SHADER, TessellationControlShader = TESSELLATION_CONTROL_SHADER, /// Tessellation evaluation shaders are executed. - TessellationEvaluationShader = TESSELLATION_EVALUATION_SHADER, + TESSELLATION_EVALUATION_SHADER, TessellationEvaluationShader = TESSELLATION_EVALUATION_SHADER, /// Geometry shaders are executed. - GeometryShader = GEOMETRY_SHADER, + GEOMETRY_SHADER, GeometryShader = GEOMETRY_SHADER, /// Fragment shaders are executed. - FragmentShader = FRAGMENT_SHADER, + FRAGMENT_SHADER, FragmentShader = FRAGMENT_SHADER, /// Early fragment tests (depth and stencil tests before fragment shading) are performed. /// Subpass load operations for framebuffer attachments with a depth/stencil format are /// performed. - EarlyFragmentTests = EARLY_FRAGMENT_TESTS, + EARLY_FRAGMENT_TESTS, EarlyFragmentTests = EARLY_FRAGMENT_TESTS, /// Late fragment tests (depth and stencil tests after fragment shading) are performed. /// Subpass store operations for framebuffer attachments with a depth/stencil format are /// performed. - LateFragmentTests = LATE_FRAGMENT_TESTS, + LATE_FRAGMENT_TESTS, LateFragmentTests = LATE_FRAGMENT_TESTS, /// The final color values are output from the pipeline after blending. /// Subpass load and store operations, multisample resolve operations for framebuffer /// attachments with a color or depth/stencil format, and `clear_attachments` are performed. - ColorAttachmentOutput = COLOR_ATTACHMENT_OUTPUT, + COLOR_ATTACHMENT_OUTPUT, ColorAttachmentOutput = COLOR_ATTACHMENT_OUTPUT, /// Compute shaders are executed. - ComputeShader = COMPUTE_SHADER, + COMPUTE_SHADER, ComputeShader = COMPUTE_SHADER, /// The set of all current and future transfer pipeline stages. /// @@ -79,13 +484,13 @@ vulkan_enum! { /// - `resolve` /// - `clear` /// - `acceleration_structure_copy` - AllTransfer = ALL_TRANSFER, + ALL_TRANSFER, AllTransfer = ALL_TRANSFER, /// A pseudo-stage representing the end of the pipeline. - BottomOfPipe = BOTTOM_OF_PIPE, + BOTTOM_OF_PIPE, BottomOfPipe = BOTTOM_OF_PIPE, /// A pseudo-stage representing reads and writes to device memory on the host. - Host = HOST, + HOST, Host = HOST, /// The set of all current and future graphics pipeline stages. /// @@ -109,49 +514,49 @@ vulkan_enum! { /// - `fragment_shading_rate_attachment` /// - `fragment_density_process` /// - `invocation_mask` - AllGraphics = ALL_GRAPHICS, + ALL_GRAPHICS, AllGraphics = ALL_GRAPHICS, /// The set of all current and future pipeline stages of all types. /// /// It is currently equivalent to setting all flags in `PipelineStages`, but automatically /// omitting any that are not supported in a given context. It also implicitly includes future /// flags that are added to Vulkan, if they are not yet supported by Vulkano. - AllCommands = ALL_COMMANDS, + ALL_COMMANDS, AllCommands = ALL_COMMANDS, /// The `copy_buffer`, `copy_image`, `copy_buffer_to_image`, `copy_image_to_buffer` and /// `copy_query_pool_results` commands are executed. - Copy = COPY { + COPY, Copy = COPY { api_version: V1_3, device_extensions: [khr_synchronization2], }, /// The `resolve_image` command is executed. - Resolve = RESOLVE { + RESOLVE, Resolve = RESOLVE { api_version: V1_3, device_extensions: [khr_synchronization2], }, /// The `blit_image` command is executed. - Blit = BLIT { + BLIT, Blit = BLIT { api_version: V1_3, device_extensions: [khr_synchronization2], }, /// The `clear_color_image`, `clear_depth_stencil_image`, `fill_buffer` and `update_buffer` /// commands are executed. - Clear = CLEAR { + CLEAR, Clear = CLEAR { api_version: V1_3, device_extensions: [khr_synchronization2], }, /// Index buffers are read. - IndexInput = INDEX_INPUT { + INDEX_INPUT, IndexInput = INDEX_INPUT { api_version: V1_3, device_extensions: [khr_synchronization2], }, /// Vertex buffers are read. - VertexAttributeInput = VERTEX_ATTRIBUTE_INPUT { + VERTEX_ATTRIBUTE_INPUT, VertexAttributeInput = VERTEX_ATTRIBUTE_INPUT { api_version: V1_3, device_extensions: [khr_synchronization2], }, @@ -167,155 +572,93 @@ vulkan_enum! { /// - `geometry_shader` /// - `task_shader` /// - `mesh_shader` - PreRasterizationShaders = PRE_RASTERIZATION_SHADERS { + PRE_RASTERIZATION_SHADERS, PreRasterizationShaders = PRE_RASTERIZATION_SHADERS { api_version: V1_3, device_extensions: [khr_synchronization2], }, /// Video decode operations are performed. - VideoDecode = VIDEO_DECODE_KHR { + VIDEO_DECODE, VideoDecode = VIDEO_DECODE_KHR { device_extensions: [khr_video_decode_queue], }, /// Video encode operations are performed. - VideoEncode = VIDEO_ENCODE_KHR { + VIDEO_ENCODE, VideoEncode = VIDEO_ENCODE_KHR { device_extensions: [khr_video_encode_queue], }, /// Vertex attribute output values are written to the transform feedback buffers. - TransformFeedback = TRANSFORM_FEEDBACK_EXT { + TRANSFORM_FEEDBACK, TransformFeedback = TRANSFORM_FEEDBACK_EXT { device_extensions: [ext_transform_feedback], }, /// The predicate of conditional rendering is read. - ConditionalRendering = CONDITIONAL_RENDERING_EXT { + CONDITIONAL_RENDERING, ConditionalRendering = CONDITIONAL_RENDERING_EXT { device_extensions: [ext_conditional_rendering], }, /// Acceleration_structure commands are executed. - AccelerationStructureBuild = ACCELERATION_STRUCTURE_BUILD_KHR { + ACCELERATION_STRUCTURE_BUILD, AccelerationStructureBuild = ACCELERATION_STRUCTURE_BUILD_KHR { device_extensions: [khr_acceleration_structure, nv_ray_tracing], }, /// The various ray tracing shader types are executed. - RayTracingShader = RAY_TRACING_SHADER_KHR { + RAY_TRACING_SHADER, RayTracingShader = RAY_TRACING_SHADER_KHR { device_extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], }, /// The fragment density map is read to generate the fragment areas. - FragmentDensityProcess = FRAGMENT_DENSITY_PROCESS_EXT { + FRAGMENT_DENSITY_PROCESS, FragmentDensityProcess = FRAGMENT_DENSITY_PROCESS_EXT { device_extensions: [ext_fragment_density_map], }, /// The fragment shading rate attachment or shading rate image is read to determine the /// fragment shading rate for portions of a rasterized primitive. - FragmentShadingRateAttachment = FRAGMENT_SHADING_RATE_ATTACHMENT_KHR { + FRAGMENT_SHADING_RATE_ATTACHMENT, FragmentShadingRateAttachment = FRAGMENT_SHADING_RATE_ATTACHMENT_KHR { device_extensions: [khr_fragment_shading_rate], }, /// Device-side preprocessing for generated commands via the `preprocess_generated_commands` /// command is handled. - CommandPreprocess = COMMAND_PREPROCESS_NV { + COMMAND_PREPROCESS, CommandPreprocess = COMMAND_PREPROCESS_NV { device_extensions: [nv_device_generated_commands], }, /// Task shaders are executed. - TaskShader = TASK_SHADER_NV { + TASK_SHADER, TaskShader = TASK_SHADER_NV { device_extensions: [nv_mesh_shader], }, /// Mesh shaders are executed. - MeshShader = MESH_SHADER_NV { + MESH_SHADER, MeshShader = MESH_SHADER_NV { device_extensions: [nv_mesh_shader], }, /// Subpass shading shaders are executed. - SubpassShading = SUBPASS_SHADING_HUAWEI { + SUBPASS_SHADING, SubpassShading = SUBPASS_SHADING_HUAWEI { device_extensions: [huawei_subpass_shading], }, /// The invocation mask image is read to optimize ray dispatch. - InvocationMask = INVOCATION_MASK_HUAWEI { + INVOCATION_MASK, InvocationMask = INVOCATION_MASK_HUAWEI { device_extensions: [huawei_invocation_mask], }, /* - AccelerationStructureCopy = ACCELERATION_STRUCTURE_COPY_KHR { + ACCELERATION_STRUCTURE_COPY, AccelerationStructureCopy = ACCELERATION_STRUCTURE_COPY_KHR { device_extensions: [khr_ray_tracing_maintenance1], }, - MicromapBuild = MICROMAP_BUILD_EXT { + MICROMAP_BUILD, MicromapBuild = MICROMAP_BUILD_EXT { device_extensions: [ext_opacity_micromap], }, - OpticalFlow = OPTICAL_FLOW_NV { + OPTICAL_FLOW, OpticalFlow = OPTICAL_FLOW_NV { device_extensions: [nv_optical_flow], }, */ } -impl PipelineStage { - #[inline] - pub fn required_queue_flags(&self) -> ash::vk::QueueFlags { - // https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap7.html#synchronization-pipeline-stages-supported - match self { - Self::TopOfPipe => ash::vk::QueueFlags::empty(), - Self::DrawIndirect => ash::vk::QueueFlags::GRAPHICS | ash::vk::QueueFlags::COMPUTE, - Self::VertexInput => ash::vk::QueueFlags::GRAPHICS, - Self::VertexShader => ash::vk::QueueFlags::GRAPHICS, - Self::TessellationControlShader => ash::vk::QueueFlags::GRAPHICS, - Self::TessellationEvaluationShader => ash::vk::QueueFlags::GRAPHICS, - Self::GeometryShader => ash::vk::QueueFlags::GRAPHICS, - Self::FragmentShader => ash::vk::QueueFlags::GRAPHICS, - Self::EarlyFragmentTests => ash::vk::QueueFlags::GRAPHICS, - Self::LateFragmentTests => ash::vk::QueueFlags::GRAPHICS, - Self::ColorAttachmentOutput => ash::vk::QueueFlags::GRAPHICS, - Self::ComputeShader => ash::vk::QueueFlags::COMPUTE, - Self::AllTransfer => { - ash::vk::QueueFlags::GRAPHICS - | ash::vk::QueueFlags::COMPUTE - | ash::vk::QueueFlags::TRANSFER - } - Self::BottomOfPipe => ash::vk::QueueFlags::empty(), - Self::Host => ash::vk::QueueFlags::empty(), - Self::AllGraphics => ash::vk::QueueFlags::GRAPHICS, - Self::AllCommands => ash::vk::QueueFlags::empty(), - Self::Copy => todo!( - "The spec doesn't currently say which queue flags support this pipeline stage" - ), - Self::Resolve => todo!( - "The spec doesn't currently say which queue flags support this pipeline stage" - ), - Self::Blit => todo!( - "The spec doesn't currently say which queue flags support this pipeline stage" - ), - Self::Clear => todo!( - "The spec doesn't currently say which queue flags support this pipeline stage" - ), - Self::IndexInput => ash::vk::QueueFlags::GRAPHICS, - Self::VertexAttributeInput => ash::vk::QueueFlags::GRAPHICS, - Self::PreRasterizationShaders => ash::vk::QueueFlags::GRAPHICS, - Self::VideoDecode => ash::vk::QueueFlags::VIDEO_DECODE_KHR, - Self::VideoEncode => ash::vk::QueueFlags::VIDEO_ENCODE_KHR, - Self::ConditionalRendering => { - ash::vk::QueueFlags::GRAPHICS | ash::vk::QueueFlags::COMPUTE - } - Self::TransformFeedback => ash::vk::QueueFlags::GRAPHICS, - Self::CommandPreprocess => ash::vk::QueueFlags::GRAPHICS | ash::vk::QueueFlags::COMPUTE, - Self::FragmentShadingRateAttachment => ash::vk::QueueFlags::GRAPHICS, - Self::TaskShader => ash::vk::QueueFlags::GRAPHICS, - Self::MeshShader => ash::vk::QueueFlags::GRAPHICS, - Self::AccelerationStructureBuild => ash::vk::QueueFlags::COMPUTE, - Self::RayTracingShader => ash::vk::QueueFlags::COMPUTE, - Self::FragmentDensityProcess => ash::vk::QueueFlags::GRAPHICS, - Self::SubpassShading => ash::vk::QueueFlags::GRAPHICS, - Self::InvocationMask => todo!( - "The spec doesn't currently say which queue flags support this pipeline stage" - ), - } - } -} - impl From for ash::vk::PipelineStageFlags { #[inline] fn from(val: PipelineStage) -> Self { @@ -323,549 +666,6 @@ impl From for ash::vk::PipelineStageFlags { } } -vulkan_bitflags! { - /// A set of stages in the device's processing pipeline. - #[non_exhaustive] - PipelineStages = PipelineStageFlags2(u64); - - /// A pseudo-stage representing the start of the pipeline. - top_of_pipe = TOP_OF_PIPE, - - /// Indirect buffers are read. - draw_indirect = DRAW_INDIRECT, - - /// Vertex and index buffers are read. - /// - /// It is currently equivalent to setting all of the following flags, but automatically - /// omitting any that are not supported in a given context. It also implicitly includes future - /// flags that are added to Vulkan, if they are not yet supported by Vulkano. - /// - `index_input` - /// - `vertex_attribute_input` - vertex_input = VERTEX_INPUT, - - /// Vertex shaders are executed. - vertex_shader = VERTEX_SHADER, - - /// Tessellation control shaders are executed. - tessellation_control_shader = TESSELLATION_CONTROL_SHADER, - - /// Tessellation evaluation shaders are executed. - tessellation_evaluation_shader = TESSELLATION_EVALUATION_SHADER, - - /// Geometry shaders are executed. - geometry_shader = GEOMETRY_SHADER, - - /// Fragment shaders are executed. - fragment_shader = FRAGMENT_SHADER, - - /// Early fragment tests (depth and stencil tests before fragment shading) are performed. - /// Subpass load operations for framebuffer attachments with a depth/stencil format are - /// performed. - early_fragment_tests = EARLY_FRAGMENT_TESTS, - - /// Late fragment tests (depth and stencil tests after fragment shading) are performed. - /// Subpass store operations for framebuffer attachments with a depth/stencil format are - /// performed. - late_fragment_tests = LATE_FRAGMENT_TESTS, - - /// The final color values are output from the pipeline after blending. - /// Subpass load and store operations, multisample resolve operations for framebuffer - /// attachments with a color or depth/stencil format, and `clear_attachments` are performed. - color_attachment_output = COLOR_ATTACHMENT_OUTPUT, - - /// Compute shaders are executed. - compute_shader = COMPUTE_SHADER, - - /// The set of all current and future transfer pipeline stages. - /// - /// It is currently equivalent to setting all of the following flags, but automatically - /// omitting any that are not supported in a given context. It also implicitly includes future - /// flags that are added to Vulkan, if they are not yet supported by Vulkano. - /// - `copy` - /// - `blit` - /// - `resolve` - /// - `clear` - /// - `acceleration_structure_copy` - all_transfer = ALL_TRANSFER, - - /// A pseudo-stage representing the end of the pipeline. - bottom_of_pipe = BOTTOM_OF_PIPE, - - /// A pseudo-stage representing reads and writes to device memory on the host. - host = HOST, - - /// The set of all current and future graphics pipeline stages. - /// - /// It is currently equivalent to setting all of the following flags, but automatically - /// omitting any that are not supported in a given context. It also implicitly includes future - /// flags that are added to Vulkan, if they are not yet supported by Vulkano. - /// - `draw_indirect` - /// - `task_shader` - /// - `mesh_shader` - /// - `vertex_input` - /// - `vertex_shader` - /// - `tessellation_control_shader` - /// - `tessellation_evaluation_shader` - /// - `geometry_shader` - /// - `fragment_shader` - /// - `early_fragment_tests` - /// - `late_fragment_tests` - /// - `color_attachment_output` - /// - `conditional_rendering` - /// - `transform_feedback` - /// - `fragment_shading_rate_attachment` - /// - `fragment_density_process` - /// - `invocation_mask` - all_graphics = ALL_GRAPHICS, - - /// The set of all current and future pipeline stages of all types. - /// - /// It is currently equivalent to setting all flags in `PipelineStages`, but automatically - /// omitting any that are not supported in a given context. It also implicitly includes future - /// flags that are added to Vulkan, if they are not yet supported by Vulkano. - all_commands = ALL_COMMANDS, - - /// The `copy_buffer`, `copy_image`, `copy_buffer_to_image`, `copy_image_to_buffer` and - /// `copy_query_pool_results` commands are executed. - copy = COPY { - api_version: V1_3, - device_extensions: [khr_synchronization2], - }, - - /// The `resolve_image` command is executed. - resolve = RESOLVE { - api_version: V1_3, - device_extensions: [khr_synchronization2], - }, - - /// The `blit_image` command is executed. - blit = BLIT { - api_version: V1_3, - device_extensions: [khr_synchronization2], - }, - - /// The `clear_color_image`, `clear_depth_stencil_image`, `fill_buffer` and `update_buffer` - /// commands are executed. - clear = CLEAR { - api_version: V1_3, - device_extensions: [khr_synchronization2], - }, - - /// Index buffers are read. - index_input = INDEX_INPUT { - api_version: V1_3, - device_extensions: [khr_synchronization2], - }, - - /// Vertex buffers are read. - vertex_attribute_input = VERTEX_ATTRIBUTE_INPUT { - api_version: V1_3, - device_extensions: [khr_synchronization2], - }, - - /// The various pre-rasterization shader types are executed. - /// - /// It is currently equivalent to setting all of the following flags, but automatically - /// omitting any that are not supported in a given context. It also implicitly includes future - /// flags that are added to Vulkan, if they are not yet supported by Vulkano. - /// - `vertex_shader` - /// - `tessellation_control_shader` - /// - `tessellation_evaluation_shader` - /// - `geometry_shader` - /// - `task_shader` - /// - `mesh_shader` - pre_rasterization_shaders = PRE_RASTERIZATION_SHADERS { - api_version: V1_3, - device_extensions: [khr_synchronization2], - }, - - /// Video decode operations are performed. - video_decode = VIDEO_DECODE_KHR { - device_extensions: [khr_video_decode_queue], - }, - - /// Video encode operations are performed. - video_encode = VIDEO_ENCODE_KHR { - device_extensions: [khr_video_encode_queue], - }, - - /// Vertex attribute output values are written to the transform feedback buffers. - transform_feedback = TRANSFORM_FEEDBACK_EXT { - device_extensions: [ext_transform_feedback], - }, - - /// The predicate of conditional rendering is read. - conditional_rendering = CONDITIONAL_RENDERING_EXT { - device_extensions: [ext_conditional_rendering], - }, - - /// Acceleration_structure commands are executed. - acceleration_structure_build = ACCELERATION_STRUCTURE_BUILD_KHR { - device_extensions: [khr_acceleration_structure, nv_ray_tracing], - }, - - /// The various ray tracing shader types are executed. - ray_tracing_shader = RAY_TRACING_SHADER_KHR { - device_extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], - }, - - /// The fragment density map is read to generate the fragment areas. - fragment_density_process = FRAGMENT_DENSITY_PROCESS_EXT { - device_extensions: [ext_fragment_density_map], - }, - - /// The fragment shading rate attachment or shading rate image is read to determine the - /// fragment shading rate for portions of a rasterized primitive. - fragment_shading_rate_attachment = FRAGMENT_SHADING_RATE_ATTACHMENT_KHR { - device_extensions: [khr_fragment_shading_rate, nv_shading_rate_image], - }, - - /// Device-side preprocessing for generated commands via the `preprocess_generated_commands` - /// command is handled. - command_preprocess = COMMAND_PREPROCESS_NV { - device_extensions: [nv_device_generated_commands], - }, - - /// Task shaders are executed. - task_shader = TASK_SHADER_NV { - device_extensions: [nv_mesh_shader], - }, - - /// Mesh shaders are executed. - mesh_shader = MESH_SHADER_NV { - device_extensions: [nv_mesh_shader], - }, - - /// Subpass shading shaders are executed. - subpass_shading = SUBPASS_SHADING_HUAWEI { - device_extensions: [huawei_subpass_shading], - }, - - /// The invocation mask image is read to optimize ray dispatch. - invocation_mask = INVOCATION_MASK_HUAWEI { - device_extensions: [huawei_invocation_mask], - }, - - /* - acceleration_structure_copy = ACCELERATION_STRUCTURE_COPY_KHR { - device_extensions: [khr_ray_tracing_maintenance1], - }, - - micromap_build = MICROMAP_BUILD_EXT { - device_extensions: [ext_opacity_micromap], - }, - - optical_flow = OPTICAL_FLOW_NV { - device_extensions: [nv_optical_flow], - }, - */ -} - -impl PipelineStages { - /// Returns whether `self` contains stages that are only available in - /// `VkPipelineStageFlagBits2`. - pub(crate) fn is_2(&self) -> bool { - !Self { - top_of_pipe: false, - draw_indirect: false, - vertex_input: false, - vertex_shader: false, - tessellation_control_shader: false, - tessellation_evaluation_shader: false, - geometry_shader: false, - fragment_shader: false, - early_fragment_tests: false, - late_fragment_tests: false, - color_attachment_output: false, - compute_shader: false, - all_transfer: false, - bottom_of_pipe: false, - host: false, - all_graphics: false, - all_commands: false, - transform_feedback: false, - conditional_rendering: false, - acceleration_structure_build: false, - ray_tracing_shader: false, - fragment_density_process: false, - fragment_shading_rate_attachment: false, - command_preprocess: false, - task_shader: false, - mesh_shader: false, - ..*self - } - .is_empty() - } - - /// Replaces and unsets flags that are equivalent to multiple other flags. - /// - /// This may set flags that are not supported by the device, so this is for internal use only - /// and should not be passed on to Vulkan. - pub(crate) fn normalize(mut self) -> Self { - if self.all_commands { - self = Self { - all_commands: false, - - top_of_pipe: true, - draw_indirect: true, - vertex_input: true, - vertex_shader: true, - tessellation_control_shader: true, - tessellation_evaluation_shader: true, - geometry_shader: true, - fragment_shader: true, - early_fragment_tests: true, - late_fragment_tests: true, - color_attachment_output: true, - compute_shader: true, - all_transfer: true, - bottom_of_pipe: true, - host: true, - all_graphics: true, - copy: true, - resolve: true, - blit: true, - clear: true, - index_input: true, - vertex_attribute_input: true, - pre_rasterization_shaders: true, - video_decode: true, - video_encode: true, - transform_feedback: true, - conditional_rendering: true, - acceleration_structure_build: true, - ray_tracing_shader: true, - fragment_density_process: true, - fragment_shading_rate_attachment: true, - command_preprocess: true, - task_shader: true, - mesh_shader: true, - subpass_shading: true, - invocation_mask: true, - _ne: crate::NonExhaustive(()), - } - } - - if self.all_graphics { - self = Self { - all_graphics: false, - - draw_indirect: true, - task_shader: true, - mesh_shader: true, - vertex_input: true, - vertex_shader: true, - tessellation_control_shader: true, - tessellation_evaluation_shader: true, - geometry_shader: true, - fragment_shader: true, - early_fragment_tests: true, - late_fragment_tests: true, - color_attachment_output: true, - transform_feedback: true, - conditional_rendering: true, - fragment_shading_rate_attachment: true, - fragment_density_process: true, - invocation_mask: true, - ..self - } - } - - if self.vertex_input { - self = Self { - vertex_input: false, - - index_input: true, - vertex_attribute_input: true, - ..self - } - } - - if self.pre_rasterization_shaders { - self = Self { - pre_rasterization_shaders: false, - - vertex_shader: true, - tessellation_control_shader: true, - tessellation_evaluation_shader: true, - geometry_shader: true, - task_shader: true, - mesh_shader: true, - ..self - } - } - - if self.all_transfer { - self = Self { - all_transfer: false, - - copy: true, - resolve: true, - blit: true, - clear: true, - //acceleration_structure_copy: true, - ..self - } - } - - self - } - - /// Returns the access types that are supported with the given pipeline stages. - /// - /// Corresponds to the table - /// "[Supported access types](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap7.html#synchronization-access-types-supported)" - /// in the Vulkan specification. - #[inline] - pub fn supported_access(&self) -> AccessFlags { - let PipelineStages { - top_of_pipe: _, - draw_indirect, - vertex_input: _, - vertex_shader, - tessellation_control_shader, - tessellation_evaluation_shader, - geometry_shader, - fragment_shader, - early_fragment_tests, - late_fragment_tests, - color_attachment_output, - compute_shader, - all_transfer: _, - bottom_of_pipe: _, - host, - all_graphics: _, - all_commands: _, - copy, - resolve, - blit, - clear, - index_input, - vertex_attribute_input, - pre_rasterization_shaders: _, - video_decode, - video_encode, - transform_feedback, - conditional_rendering, - acceleration_structure_build, - ray_tracing_shader, - fragment_density_process, - fragment_shading_rate_attachment, - command_preprocess, - task_shader, - mesh_shader, - subpass_shading, - invocation_mask, - //acceleration_structure_copy, - _ne: _, - } = self.normalize(); - - AccessFlags { - indirect_command_read: draw_indirect || acceleration_structure_build, - index_read: index_input, - vertex_attribute_read: vertex_attribute_input, - uniform_read: task_shader - || mesh_shader - || ray_tracing_shader - || vertex_shader - || tessellation_control_shader - || tessellation_evaluation_shader - || geometry_shader - || fragment_shader - || compute_shader, - shader_read: acceleration_structure_build - || task_shader - || mesh_shader - || ray_tracing_shader - // || micromap_build - || vertex_shader - || tessellation_control_shader - || tessellation_evaluation_shader - || geometry_shader - || fragment_shader - || compute_shader, - shader_write: task_shader - || mesh_shader - || ray_tracing_shader - || vertex_shader - || tessellation_control_shader - || tessellation_evaluation_shader - || geometry_shader - || fragment_shader - || compute_shader, - input_attachment_read: subpass_shading || fragment_shader, - color_attachment_read: color_attachment_output, - color_attachment_write: color_attachment_output, - depth_stencil_attachment_read: early_fragment_tests || late_fragment_tests, - depth_stencil_attachment_write: early_fragment_tests || late_fragment_tests, - transfer_read: copy || blit || resolve || acceleration_structure_build, - transfer_write: copy || blit || resolve || clear || acceleration_structure_build, - host_read: host, - host_write: host, - memory_read: true, - memory_write: true, - shader_sampled_read: acceleration_structure_build - || task_shader - || mesh_shader - || ray_tracing_shader - // || micromap_build - || vertex_shader - || tessellation_control_shader - || tessellation_evaluation_shader - || geometry_shader - || fragment_shader - || compute_shader, - shader_storage_read: acceleration_structure_build - || task_shader - || mesh_shader - || ray_tracing_shader - // || micromap_build - || vertex_shader - || tessellation_control_shader - || tessellation_evaluation_shader - || geometry_shader - || fragment_shader - || compute_shader, - shader_storage_write: acceleration_structure_build - || task_shader - || mesh_shader - || ray_tracing_shader - || vertex_shader - || tessellation_control_shader - || tessellation_evaluation_shader - || geometry_shader - || fragment_shader - || compute_shader, - video_decode_read: video_decode, - video_decode_write: video_decode, - video_encode_read: video_encode, - video_encode_write: video_encode, - transform_feedback_write: transform_feedback, - transform_feedback_counter_write: transform_feedback, - transform_feedback_counter_read: transform_feedback || draw_indirect, - conditional_rendering_read: conditional_rendering, - command_preprocess_read: command_preprocess, - command_preprocess_write: command_preprocess, - fragment_shading_rate_attachment_read: fragment_shading_rate_attachment, - acceleration_structure_read: task_shader - || mesh_shader - || vertex_shader - || tessellation_control_shader - || tessellation_evaluation_shader - || geometry_shader - || fragment_shader - || compute_shader - || ray_tracing_shader - || acceleration_structure_build, - acceleration_structure_write: acceleration_structure_build, - fragment_density_map_read: fragment_density_process, - color_attachment_read_noncoherent: color_attachment_output, - invocation_mask_read: invocation_mask, - _ne: crate::NonExhaustive(()), - } - } -} - impl From for ash::vk::PipelineStageFlags { #[inline] fn from(val: PipelineStages) -> Self { @@ -873,78 +673,91 @@ impl From for ash::vk::PipelineStageFlags { } } -impl From for PipelineStages { - #[inline] - fn from(val: PipelineStage) -> Self { - let mut result = Self::empty(); +vulkan_bitflags! { + #[non_exhaustive] - match val { - PipelineStage::TopOfPipe => result.top_of_pipe = true, - PipelineStage::DrawIndirect => result.draw_indirect = true, - PipelineStage::VertexInput => result.vertex_input = true, - PipelineStage::VertexShader => result.vertex_shader = true, - PipelineStage::TessellationControlShader => result.tessellation_control_shader = true, - PipelineStage::TessellationEvaluationShader => { - result.tessellation_evaluation_shader = true - } - PipelineStage::GeometryShader => result.geometry_shader = true, - PipelineStage::FragmentShader => result.fragment_shader = true, - PipelineStage::EarlyFragmentTests => result.early_fragment_tests = true, - PipelineStage::LateFragmentTests => result.late_fragment_tests = true, - PipelineStage::ColorAttachmentOutput => result.color_attachment_output = true, - PipelineStage::ComputeShader => result.compute_shader = true, - PipelineStage::AllTransfer => result.all_transfer = true, - PipelineStage::BottomOfPipe => result.bottom_of_pipe = true, - PipelineStage::Host => result.host = true, - PipelineStage::AllGraphics => result.all_graphics = true, - PipelineStage::AllCommands => result.all_commands = true, - PipelineStage::Copy => result.copy = true, - PipelineStage::Resolve => result.resolve = true, - PipelineStage::Blit => result.blit = true, - PipelineStage::Clear => result.clear = true, - PipelineStage::IndexInput => result.index_input = true, - PipelineStage::VertexAttributeInput => result.vertex_attribute_input = true, - PipelineStage::PreRasterizationShaders => result.pre_rasterization_shaders = true, - PipelineStage::VideoDecode => result.video_decode = true, - PipelineStage::VideoEncode => result.video_encode = true, - PipelineStage::TransformFeedback => result.transform_feedback = true, - PipelineStage::ConditionalRendering => result.conditional_rendering = true, - PipelineStage::AccelerationStructureBuild => result.acceleration_structure_build = true, - PipelineStage::RayTracingShader => result.ray_tracing_shader = true, - PipelineStage::FragmentDensityProcess => result.fragment_density_process = true, - PipelineStage::FragmentShadingRateAttachment => { - result.fragment_shading_rate_attachment = true - } - PipelineStage::CommandPreprocess => result.command_preprocess = true, - PipelineStage::TaskShader => result.task_shader = true, - PipelineStage::MeshShader => result.mesh_shader = true, - PipelineStage::SubpassShading => result.subpass_shading = true, - PipelineStage::InvocationMask => result.invocation_mask = true, + /// A set of memory access types that are included in a memory dependency. + AccessFlags impl { + /// Returns whether `self` contains stages that are only available in + /// `VkAccessFlagBits2`. + pub(crate) fn is_2(self) -> bool { + !(self + - (AccessFlags::INDIRECT_COMMAND_READ + | AccessFlags::INDEX_READ + | AccessFlags::VERTEX_ATTRIBUTE_READ + | AccessFlags::UNIFORM_READ + | AccessFlags::INPUT_ATTACHMENT_READ + | AccessFlags::SHADER_READ + | AccessFlags::SHADER_WRITE + | AccessFlags::COLOR_ATTACHMENT_READ + | AccessFlags::COLOR_ATTACHMENT_WRITE + | AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ + | AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE + | AccessFlags::TRANSFER_READ + | AccessFlags::TRANSFER_WRITE + | AccessFlags::HOST_READ + | AccessFlags::HOST_WRITE + | AccessFlags::MEMORY_READ + | AccessFlags::MEMORY_WRITE + | AccessFlags::SHADER_SAMPLED_READ + | AccessFlags::SHADER_STORAGE_READ + | AccessFlags::SHADER_STORAGE_WRITE + | AccessFlags::VIDEO_DECODE_READ + | AccessFlags::VIDEO_DECODE_WRITE + | AccessFlags::VIDEO_ENCODE_READ + | AccessFlags::VIDEO_ENCODE_WRITE + | AccessFlags::TRANSFORM_FEEDBACK_WRITE + | AccessFlags::TRANSFORM_FEEDBACK_COUNTER_READ + | AccessFlags::TRANSFORM_FEEDBACK_COUNTER_WRITE + | AccessFlags::CONDITIONAL_RENDERING_READ + | AccessFlags::COMMAND_PREPROCESS_READ + | AccessFlags::COMMAND_PREPROCESS_WRITE + | AccessFlags::FRAGMENT_SHADING_RATE_ATTACHMENT_READ + | AccessFlags::ACCELERATION_STRUCTURE_READ + | AccessFlags::ACCELERATION_STRUCTURE_WRITE + | AccessFlags::FRAGMENT_DENSITY_MAP_READ + | AccessFlags::COLOR_ATTACHMENT_READ_NONCOHERENT + | AccessFlags::INVOCATION_MASK_READ)) + .is_empty() } - result - } -} + /// Replaces and unsets flags that are equivalent to multiple other flags. + /// + /// This may set flags that are not supported by the device, so this is for internal use only + /// and should not be passed on to Vulkan. + #[allow(dead_code)] // TODO: use this function + pub(crate) fn normalize(mut self) -> Self { + if self.intersects(AccessFlags::SHADER_READ) { + self -= AccessFlags::SHADER_READ; + self |= AccessFlags::UNIFORM_READ + | AccessFlags::SHADER_SAMPLED_READ + | AccessFlags::SHADER_STORAGE_READ; + } -vulkan_bitflags! { - /// A set of memory access types that are included in a memory dependency. - #[non_exhaustive] - AccessFlags = AccessFlags2(u64); + if self.intersects(AccessFlags::SHADER_WRITE) { + self -= AccessFlags::SHADER_WRITE; + self |= AccessFlags::SHADER_STORAGE_WRITE; + } + + self + } + } + = AccessFlags2(u64); /// Read access to an indirect buffer. - indirect_command_read = INDIRECT_COMMAND_READ, + INDIRECT_COMMAND_READ = INDIRECT_COMMAND_READ, /// Read access to an index buffer. - index_read = INDEX_READ, + INDEX_READ = INDEX_READ, /// Read access to a vertex buffer. - vertex_attribute_read = VERTEX_ATTRIBUTE_READ, + VERTEX_ATTRIBUTE_READ = VERTEX_ATTRIBUTE_READ, /// Read access to a uniform buffer in a shader. - uniform_read = UNIFORM_READ, + UNIFORM_READ = UNIFORM_READ, /// Read access to an input attachment in a fragment shader, within a render pass. - input_attachment_read = INPUT_ATTACHMENT_READ, + INPUT_ATTACHMENT_READ = INPUT_ATTACHMENT_READ, /// Read access to a buffer or image in a shader. /// @@ -954,244 +767,176 @@ vulkan_bitflags! { /// - `uniform_read` /// - `shader_sampled_read` /// - `shader_storage_read` - shader_read = SHADER_READ, + SHADER_READ = SHADER_READ, /// Write access to a buffer or image in a shader. /// /// It is currently equivalent to `shader_storage_write`. It also implicitly includes future /// flags that are added to Vulkan, if they are not yet supported by Vulkano. - shader_write = SHADER_WRITE, + SHADER_WRITE = SHADER_WRITE, /// Read access to a color attachment during blending, logic operations or /// subpass load operations. - color_attachment_read = COLOR_ATTACHMENT_READ, + COLOR_ATTACHMENT_READ = COLOR_ATTACHMENT_READ, /// Write access to a color, resolve or depth/stencil resolve attachment during a render pass /// or subpass store operations. - color_attachment_write = COLOR_ATTACHMENT_WRITE, + COLOR_ATTACHMENT_WRITE = COLOR_ATTACHMENT_WRITE, /// Read access to a depth/stencil attachment during depth/stencil operations or /// subpass load operations. - depth_stencil_attachment_read = DEPTH_STENCIL_ATTACHMENT_READ, + DEPTH_STENCIL_ATTACHMENT_READ = DEPTH_STENCIL_ATTACHMENT_READ, /// Write access to a depth/stencil attachment during depth/stencil operations or /// subpass store operations. - depth_stencil_attachment_write = DEPTH_STENCIL_ATTACHMENT_WRITE, + DEPTH_STENCIL_ATTACHMENT_WRITE = DEPTH_STENCIL_ATTACHMENT_WRITE, /// Read access to a buffer or image during a copy, blit or resolve command. - transfer_read = TRANSFER_READ, + TRANSFER_READ = TRANSFER_READ, /// Write access to a buffer or image during a copy, blit, resolve or clear command. - transfer_write = TRANSFER_WRITE, + TRANSFER_WRITE = TRANSFER_WRITE, /// Read access performed by the host. - host_read = HOST_READ, + HOST_READ = HOST_READ, /// Write access performed by the host. - host_write = HOST_WRITE, + HOST_WRITE = HOST_WRITE, /// Any type of read access. /// /// This is equivalent to setting all `_read` flags that are allowed in the given context. - memory_read = MEMORY_READ, + MEMORY_READ = MEMORY_READ, /// Any type of write access. /// /// This is equivalent to setting all `_write` flags that are allowed in the given context. - memory_write = MEMORY_WRITE, + MEMORY_WRITE = MEMORY_WRITE, /// Read access to a uniform texel buffer or sampled image in a shader. - shader_sampled_read = SHADER_SAMPLED_READ { + SHADER_SAMPLED_READ = SHADER_SAMPLED_READ { api_version: V1_3, device_extensions: [khr_synchronization2], }, /// Read access to a storage buffer, storage texel buffer or storage image in a shader. - shader_storage_read = SHADER_STORAGE_READ { + SHADER_STORAGE_READ = SHADER_STORAGE_READ { api_version: V1_3, device_extensions: [khr_synchronization2], }, /// Write access to a storage buffer, storage texel buffer or storage image in a shader. - shader_storage_write = SHADER_STORAGE_WRITE { + SHADER_STORAGE_WRITE = SHADER_STORAGE_WRITE { api_version: V1_3, device_extensions: [khr_synchronization2], }, /// Read access to an image or buffer as part of a video decode operation. - video_decode_read = VIDEO_DECODE_READ_KHR { + VIDEO_DECODE_READ = VIDEO_DECODE_READ_KHR { device_extensions: [khr_video_decode_queue], }, /// Write access to an image or buffer as part of a video decode operation. - video_decode_write = VIDEO_DECODE_WRITE_KHR { + VIDEO_DECODE_WRITE = VIDEO_DECODE_WRITE_KHR { device_extensions: [khr_video_decode_queue], }, /// Read access to an image or buffer as part of a video encode operation. - video_encode_read = VIDEO_ENCODE_READ_KHR { + VIDEO_ENCODE_READ = VIDEO_ENCODE_READ_KHR { device_extensions: [khr_video_encode_queue], }, /// Write access to an image or buffer as part of a video encode operation. - video_encode_write = VIDEO_ENCODE_WRITE_KHR { + VIDEO_ENCODE_WRITE = VIDEO_ENCODE_WRITE_KHR { device_extensions: [khr_video_encode_queue], }, /// Write access to a transform feedback buffer during transform feedback operations. - transform_feedback_write = TRANSFORM_FEEDBACK_WRITE_EXT { + TRANSFORM_FEEDBACK_WRITE = TRANSFORM_FEEDBACK_WRITE_EXT { device_extensions: [ext_transform_feedback], }, /// Read access to a transform feedback counter buffer during transform feedback operations. - transform_feedback_counter_read = TRANSFORM_FEEDBACK_COUNTER_READ_EXT { + TRANSFORM_FEEDBACK_COUNTER_READ = TRANSFORM_FEEDBACK_COUNTER_READ_EXT { device_extensions: [ext_transform_feedback], }, /// Write access to a transform feedback counter buffer during transform feedback operations. - transform_feedback_counter_write = TRANSFORM_FEEDBACK_COUNTER_WRITE_EXT { + TRANSFORM_FEEDBACK_COUNTER_WRITE = TRANSFORM_FEEDBACK_COUNTER_WRITE_EXT { device_extensions: [ext_transform_feedback], }, /// Read access to a predicate during conditional rendering. - conditional_rendering_read = CONDITIONAL_RENDERING_READ_EXT { + CONDITIONAL_RENDERING_READ = CONDITIONAL_RENDERING_READ_EXT { device_extensions: [ext_conditional_rendering], }, /// Read access to preprocess buffers input to `preprocess_generated_commands`. - command_preprocess_read = COMMAND_PREPROCESS_READ_NV { + COMMAND_PREPROCESS_READ = COMMAND_PREPROCESS_READ_NV { device_extensions: [nv_device_generated_commands], }, /// Read access to sequences buffers output by `preprocess_generated_commands`. - command_preprocess_write = COMMAND_PREPROCESS_WRITE_NV { + COMMAND_PREPROCESS_WRITE = COMMAND_PREPROCESS_WRITE_NV { device_extensions: [nv_device_generated_commands], }, /// Read access to a fragment shading rate attachment during rasterization. - fragment_shading_rate_attachment_read = FRAGMENT_SHADING_RATE_ATTACHMENT_READ_KHR { + FRAGMENT_SHADING_RATE_ATTACHMENT_READ = FRAGMENT_SHADING_RATE_ATTACHMENT_READ_KHR { device_extensions: [khr_fragment_shading_rate], }, /// Read access to an acceleration structure or acceleration structure scratch buffer during /// trace, build or copy commands. - acceleration_structure_read = ACCELERATION_STRUCTURE_READ_KHR { + ACCELERATION_STRUCTURE_READ = ACCELERATION_STRUCTURE_READ_KHR { device_extensions: [khr_acceleration_structure, nv_ray_tracing], }, /// Write access to an acceleration structure or acceleration structure scratch buffer during /// trace, build or copy commands. - acceleration_structure_write = ACCELERATION_STRUCTURE_WRITE_KHR { + ACCELERATION_STRUCTURE_WRITE = ACCELERATION_STRUCTURE_WRITE_KHR { device_extensions: [khr_acceleration_structure, nv_ray_tracing], }, /// Read access to a fragment density map attachment during dynamic fragment density map /// operations. - fragment_density_map_read = FRAGMENT_DENSITY_MAP_READ_EXT { + FRAGMENT_DENSITY_MAP_READ = FRAGMENT_DENSITY_MAP_READ_EXT { device_extensions: [ext_fragment_density_map], }, /// Read access to color attachments when performing advanced blend operations. - color_attachment_read_noncoherent = COLOR_ATTACHMENT_READ_NONCOHERENT_EXT { + COLOR_ATTACHMENT_READ_NONCOHERENT = COLOR_ATTACHMENT_READ_NONCOHERENT_EXT { device_extensions: [ext_blend_operation_advanced], }, /// Read access to an invocation mask image. - invocation_mask_read = INVOCATION_MASK_READ_HUAWEI { + INVOCATION_MASK_READ = INVOCATION_MASK_READ_HUAWEI { device_extensions: [huawei_invocation_mask], }, /* - shader_binding_table_read = SHADER_BINDING_TABLE_READ_KHR { + SHADER_BINDING_TABLE_READ = SHADER_BINDING_TABLE_READ_KHR { device_extensions: [khr_ray_tracing_maintenance1], }, - micromap_read = MICROMAP_READ_EXT { + MICROMAP_READ = MICROMAP_READ_EXT { device_extensions: [ext_opacity_micromap], }, - micromap_write = MICROMAP_WRITE_EXT { + MICROMAP_WRITE = MICROMAP_WRITE_EXT { device_extensions: [ext_opacity_micromap], }, - optical_flow_read = OPTICAL_FLOW_READ_NV { + OPTICAL_FLOW_READ = OPTICAL_FLOW_READ_NV { device_extensions: [nv_optical_flow], }, - optical_flow_write = OPTICAL_FLOW_WRITE_NV { + OPTICAL_FLOW_WRITE = OPTICAL_FLOW_WRITE_NV { device_extensions: [nv_optical_flow], }, */ } -impl AccessFlags { - /// Returns whether `self` contains stages that are only available in - /// `VkAccessFlagBits2`. - pub(crate) fn is_2(&self) -> bool { - !Self { - indirect_command_read: false, - index_read: false, - vertex_attribute_read: false, - uniform_read: false, - input_attachment_read: false, - shader_read: false, - shader_write: false, - color_attachment_read: false, - color_attachment_write: false, - depth_stencil_attachment_read: false, - depth_stencil_attachment_write: false, - transfer_read: false, - transfer_write: false, - host_read: false, - host_write: false, - memory_read: false, - memory_write: false, - transform_feedback_write: false, - transform_feedback_counter_read: false, - transform_feedback_counter_write: false, - conditional_rendering_read: false, - color_attachment_read_noncoherent: false, - acceleration_structure_read: false, - acceleration_structure_write: false, - fragment_density_map_read: false, - fragment_shading_rate_attachment_read: false, - command_preprocess_read: false, - command_preprocess_write: false, - ..*self - } - .is_empty() - } - - /// Replaces and unsets flags that are equivalent to multiple other flags. - /// - /// This may set flags that are not supported by the device, so this is for internal use only - /// and should not be passed on to Vulkan. - #[allow(dead_code)] // TODO: use this function - pub(crate) fn normalize(mut self) -> Self { - if self.shader_read { - self = Self { - shader_read: false, - - uniform_read: true, - shader_sampled_read: true, - shader_storage_read: true, - ..self - } - } - - if self.shader_write { - self = Self { - shader_write: false, - - shader_storage_write: true, - ..self - } - } - - self - } -} - impl From for ash::vk::AccessFlags { #[inline] fn from(val: AccessFlags) -> Self { diff --git a/vulkano/src/sync/semaphore.rs b/vulkano/src/sync/semaphore.rs index 2c46485a..2209af20 100644 --- a/vulkano/src/sync/semaphore.rs +++ b/vulkano/src/sync/semaphore.rs @@ -9,7 +9,7 @@ use crate::{ device::{Device, DeviceOwned, Queue}, - macros::{vulkan_bitflags, vulkan_enum}, + macros::{vulkan_bitflags, vulkan_bitflags_enum}, OomError, RequirementNotMet, RequiresOneOf, Version, VulkanError, VulkanObject, }; use parking_lot::{Mutex, MutexGuard}; @@ -94,7 +94,7 @@ impl Semaphore { if !external_semaphore_properties .compatible_handle_types - .contains(&export_handle_types) + .contains(export_handle_types) { return Err(SemaphoreError::ExportHandleTypesNotCompatible); } @@ -234,7 +234,7 @@ impl Semaphore { ) -> Result<(), SemaphoreError> { if !self.device.enabled_extensions().khr_external_semaphore_fd { return Err(SemaphoreError::RequirementNotMet { - required_for: "`export_fd`", + required_for: "`Semaphore::export_fd`", requires_one_of: RequiresOneOf { device_extensions: &["khr_external_semaphore_fd"], ..Default::default() @@ -246,7 +246,7 @@ impl Semaphore { handle_type.validate_device(&self.device)?; // VUID-VkSemaphoreGetFdInfoKHR-handleType-01132 - if !self.export_handle_types.intersects(&handle_type.into()) { + if !self.export_handle_types.intersects(handle_type.into()) { return Err(SemaphoreError::HandleTypeNotEnabled); } @@ -267,7 +267,7 @@ impl Semaphore { if !external_semaphore_properties .export_from_imported_handle_types - .intersects(&imported_handle_type.into()) + .intersects(imported_handle_type.into()) { return Err(SemaphoreError::ExportFromImportedNotSupported { imported_handle_type, @@ -369,7 +369,7 @@ impl Semaphore { .khr_external_semaphore_win32 { return Err(SemaphoreError::RequirementNotMet { - required_for: "`export_win32_handle`", + required_for: "`Semaphore::export_win32_handle`", requires_one_of: RequiresOneOf { device_extensions: &["khr_external_semaphore_win32"], ..Default::default() @@ -381,7 +381,7 @@ impl Semaphore { handle_type.validate_device(&self.device)?; // VUID-VkSemaphoreGetWin32HandleInfoKHR-handleType-01126 - if !self.export_handle_types.intersects(&handle_type.into()) { + if !self.export_handle_types.intersects(handle_type.into()) { return Err(SemaphoreError::HandleTypeNotEnabled); } @@ -411,7 +411,7 @@ impl Semaphore { if !external_semaphore_properties .export_from_imported_handle_types - .intersects(&imported_handle_type.into()) + .intersects(imported_handle_type.into()) { return Err(SemaphoreError::ExportFromImportedNotSupported { imported_handle_type, @@ -504,7 +504,7 @@ impl Semaphore { ) -> Result<(), SemaphoreError> { if !self.device.enabled_extensions().fuchsia_external_semaphore { return Err(SemaphoreError::RequirementNotMet { - required_for: "`export_zircon_handle`", + required_for: "`Semaphore::export_zircon_handle`", requires_one_of: RequiresOneOf { device_extensions: &["fuchsia_external_semaphore"], ..Default::default() @@ -635,7 +635,7 @@ impl Semaphore { ) -> Result<(), SemaphoreError> { if !self.device.enabled_extensions().khr_external_semaphore_fd { return Err(SemaphoreError::RequirementNotMet { - required_for: "`import_fd`", + required_for: "`Semaphore::import_fd`", requires_one_of: RequiresOneOf { device_extensions: &["khr_external_semaphore_fd"], ..Default::default() @@ -674,7 +674,8 @@ impl Semaphore { // Can't validate, therefore unsafe // VUID-VkImportSemaphoreFdInfoKHR-handleType-07307 - if handle_type.has_copy_transference() && !flags.temporary { + if handle_type.has_copy_transference() && !flags.intersects(SemaphoreImportFlags::TEMPORARY) + { return Err(SemaphoreError::HandletypeCopyNotTemporary); } @@ -720,7 +721,10 @@ impl Semaphore { .result() .map_err(VulkanError::from)?; - state.import(handle_type, flags.temporary); + state.import( + handle_type, + flags.intersects(SemaphoreImportFlags::TEMPORARY), + ); Ok(()) } @@ -760,7 +764,7 @@ impl Semaphore { .khr_external_semaphore_win32 { return Err(SemaphoreError::RequirementNotMet { - required_for: "`import_win32_handle`", + required_for: "`Semaphore::import_win32_handle`", requires_one_of: RequiresOneOf { device_extensions: &["khr_external_semaphore_win32"], ..Default::default() @@ -800,7 +804,8 @@ impl Semaphore { // Can't validate, therefore unsafe // VUID? - if handle_type.has_copy_transference() && !flags.temporary { + if handle_type.has_copy_transference() && !flags.intersects(SemaphoreImportFlags::TEMPORARY) + { return Err(SemaphoreError::HandletypeCopyNotTemporary); } @@ -846,7 +851,10 @@ impl Semaphore { .result() .map_err(VulkanError::from)?; - state.import(handle_type, flags.temporary); + state.import( + handle_type, + flags.intersects(SemaphoreImportFlags::TEMPORARY), + ); Ok(()) } @@ -883,7 +891,7 @@ impl Semaphore { ) -> Result<(), SemaphoreError> { if !self.device.enabled_extensions().fuchsia_external_semaphore { return Err(SemaphoreError::RequirementNotMet { - required_for: "`import_zircon_handle`", + required_for: "`Semaphore::import_zircon_handle`", requires_one_of: RequiresOneOf { device_extensions: &["fuchsia_external_semaphore"], ..Default::default() @@ -918,7 +926,8 @@ impl Semaphore { // VUID-VkImportSemaphoreZirconHandleInfoFUCHSIA-zirconHandle-04767 // Can't validate, therefore unsafe - if handle_type.has_copy_transference() && !flags.temporary { + if handle_type.has_copy_transference() && !flags.intersects(SemaphoreImportFlags::TEMPORARY) + { return Err(SemaphoreError::HandletypeCopyNotTemporary); } @@ -963,7 +972,10 @@ impl Semaphore { .result() .map_err(VulkanError::from)?; - state.import(handle_type, flags.temporary); + state.import( + handle_type, + flags.intersects(SemaphoreImportFlags::TEMPORARY), + ); Ok(()) } @@ -1059,7 +1071,7 @@ impl SemaphoreState { #[allow(dead_code)] #[inline] fn is_exported(&self, handle_type: ExternalSemaphoreHandleType) -> bool { - self.exported_handle_types.intersects(&handle_type.into()) + self.exported_handle_types.intersects(handle_type.into()) } #[inline] @@ -1157,158 +1169,78 @@ impl Default for SemaphoreCreateInfo { } } -vulkan_enum! { - /// The handle type used for Vulkan external semaphore APIs. +vulkan_bitflags_enum! { #[non_exhaustive] - ExternalSemaphoreHandleType = ExternalSemaphoreHandleTypeFlags(u32); - /// A POSIX file descriptor handle that is only usable with Vulkan and compatible APIs. - /// - /// This handle type has *reference transference*. - OpaqueFd = OPAQUE_FD, + /// A set of [`ExternalSemaphoreHandleType`] values. + ExternalSemaphoreHandleTypes, - /// A Windows NT handle that is only usable with Vulkan and compatible APIs. - /// - /// This handle type has *reference transference*. - OpaqueWin32 = OPAQUE_WIN32, - - /// A Windows global share handle that is only usable with Vulkan and compatible APIs. - /// - /// This handle type has *reference transference*. - OpaqueWin32Kmt = OPAQUE_WIN32_KMT, - - /// A Windows NT handle that refers to a Direct3D 11 or 12 fence. - /// - /// This handle type has *reference transference*. - D3D12Fence = D3D12_FENCE, - - /// A POSIX file descriptor handle to a Linux Sync File or Android Fence object. - /// - /// This handle type has *copy transference*. - SyncFd = SYNC_FD, - - /// A handle to a Zircon event object. - /// - /// This handle type has *reference transference*. - /// - /// The - /// [`fuchsia_external_semaphore`](crate::device::DeviceExtensions::fuchsia_external_semaphore) - /// extension must be enabled on the device. - ZirconEvent = ZIRCON_EVENT_FUCHSIA { - device_extensions: [fuchsia_external_semaphore], - }, -} - -impl ExternalSemaphoreHandleType { - /// Returns whether the given handle type has *copy transference* rather than *reference - /// transference*. - /// - /// Imports of handles with copy transference must always be temporary. Exports of such - /// handles must only occur if no queue is waiting on the semaphore, and only if the semaphore - /// is already signaled, or if there is a semaphore signal operation pending in a queue. - #[inline] - pub fn has_copy_transference(&self) -> bool { - // As defined by - // https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap7.html#synchronization-semaphore-handletypes-win32 - // https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap7.html#synchronization-semaphore-handletypes-fd - // https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap7.html#synchronization-semaphore-handletypes-fuchsia - matches!(self, Self::SyncFd) - } -} - -vulkan_bitflags! { - /// A mask of multiple external semaphore handle types. - #[non_exhaustive] - ExternalSemaphoreHandleTypes = ExternalSemaphoreHandleTypeFlags(u32); - - /// A POSIX file descriptor handle that is only usable with Vulkan and compatible APIs. - /// - /// This handle type has *reference transference*. - opaque_fd = OPAQUE_FD, - - /// A Windows NT handle that is only usable with Vulkan and compatible APIs. - /// - /// This handle type has *reference transference*. - opaque_win32 = OPAQUE_WIN32, - - /// A Windows global share handle that is only usable with Vulkan and compatible APIs. - /// - /// This handle type has *reference transference*. - opaque_win32_kmt = OPAQUE_WIN32_KMT, - - /// A Windows NT handle that refers to a Direct3D 11 or 12 fence. - /// - /// This handle type has *reference transference*. - d3d12_fence = D3D12_FENCE, - - /// A POSIX file descriptor handle to a Linux Sync File or Android Fence object. - /// - /// This handle type has *copy transference*. - sync_fd = SYNC_FD, - - /// A handle to a Zircon event object. - /// - /// This handle type has *reference transference*. - /// - /// The - /// [`fuchsia_external_semaphore`](crate::device::DeviceExtensions::fuchsia_external_semaphore) - /// extension must be enabled on the device. - zircon_event = ZIRCON_EVENT_FUCHSIA { - device_extensions: [fuchsia_external_semaphore], - }, -} - -impl From for ExternalSemaphoreHandleTypes { - #[inline] - fn from(val: ExternalSemaphoreHandleType) -> Self { - let mut result = Self::empty(); - - match val { - ExternalSemaphoreHandleType::OpaqueFd => result.opaque_fd = true, - ExternalSemaphoreHandleType::OpaqueWin32 => result.opaque_win32 = true, - ExternalSemaphoreHandleType::OpaqueWin32Kmt => result.opaque_win32_kmt = true, - ExternalSemaphoreHandleType::D3D12Fence => result.d3d12_fence = true, - ExternalSemaphoreHandleType::SyncFd => result.sync_fd = true, - ExternalSemaphoreHandleType::ZirconEvent => result.zircon_event = true, + /// The handle type used to export or import semaphores to/from an external source. + ExternalSemaphoreHandleType impl { + /// Returns whether the given handle type has *copy transference* rather than *reference + /// transference*. + /// + /// Imports of handles with copy transference must always be temporary. Exports of such + /// handles must only occur if no queue is waiting on the semaphore, and only if the semaphore + /// is already signaled, or if there is a semaphore signal operation pending in a queue. + #[inline] + pub fn has_copy_transference(self) -> bool { + // As defined by + // https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap7.html#synchronization-semaphore-handletypes-win32 + // https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap7.html#synchronization-semaphore-handletypes-fd + // https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap7.html#synchronization-semaphore-handletypes-fuchsia + matches!(self, Self::SyncFd) } + }, - result - } -} + = ExternalSemaphoreHandleTypeFlags(u32); -impl ExternalSemaphoreHandleTypes { - fn into_iter(self) -> impl IntoIterator { - let Self { - opaque_fd, - opaque_win32, - opaque_win32_kmt, - d3d12_fence, - sync_fd, - zircon_event, - _ne: _, - } = self; + /// A POSIX file descriptor handle that is only usable with Vulkan and compatible APIs. + /// + /// This handle type has *reference transference*. + OPAQUE_FD, OpaqueFd = OPAQUE_FD, - [ - opaque_fd.then_some(ExternalSemaphoreHandleType::OpaqueFd), - opaque_win32.then_some(ExternalSemaphoreHandleType::OpaqueWin32), - opaque_win32_kmt.then_some(ExternalSemaphoreHandleType::OpaqueWin32Kmt), - d3d12_fence.then_some(ExternalSemaphoreHandleType::D3D12Fence), - sync_fd.then_some(ExternalSemaphoreHandleType::SyncFd), - zircon_event.then_some(ExternalSemaphoreHandleType::ZirconEvent), - ] - .into_iter() - .flatten() - } + /// A Windows NT handle that is only usable with Vulkan and compatible APIs. + /// + /// This handle type has *reference transference*. + OPAQUE_WIN32, OpaqueWin32 = OPAQUE_WIN32, + + /// A Windows global share handle that is only usable with Vulkan and compatible APIs. + /// + /// This handle type has *reference transference*. + OPAQUE_WIN32_KMT, OpaqueWin32Kmt = OPAQUE_WIN32_KMT, + + /// A Windows NT handle that refers to a Direct3D 11 or 12 fence. + /// + /// This handle type has *reference transference*. + D3D12_FENCE, D3D12Fence = D3D12_FENCE, + + /// A POSIX file descriptor handle to a Linux Sync File or Android Fence object. + /// + /// This handle type has *copy transference*. + SYNC_FD, SyncFd = SYNC_FD, + + /// A handle to a Zircon event object. + /// + /// This handle type has *reference transference*. + /// + /// The [`fuchsia_external_semaphore`] extension must be enabled on the device. + /// + /// [`fuchsia_external_semaphore`]: crate::device::DeviceExtensions::fuchsia_external_semaphore + ZIRCON_EVENT, ZirconEvent = ZIRCON_EVENT_FUCHSIA { + device_extensions: [fuchsia_external_semaphore], + }, } vulkan_bitflags! { - /// Additional parameters for a semaphore payload import. #[non_exhaustive] + + /// Additional parameters for a semaphore payload import. SemaphoreImportFlags = SemaphoreImportFlags(u32); /// The semaphore payload will be imported only temporarily, regardless of the permanence of the /// imported handle type. - temporary = TEMPORARY, + TEMPORARY = TEMPORARY, } #[cfg(unix)] @@ -1718,10 +1650,7 @@ mod tests { let sem = Semaphore::new( device, SemaphoreCreateInfo { - export_handle_types: ExternalSemaphoreHandleTypes { - opaque_fd: true, - ..ExternalSemaphoreHandleTypes::empty() - }, + export_handle_types: ExternalSemaphoreHandleTypes::OPAQUE_FD, ..Default::default() }, ) diff --git a/vulkano/src/tests.rs b/vulkano/src/tests.rs index 69264dbe..d8b6ebbd 100644 --- a/vulkano/src/tests.rs +++ b/vulkano/src/tests.rs @@ -52,7 +52,7 @@ macro_rules! gfx_dev_and_queue { }) .filter_map(|p| { p.queue_family_properties().iter() - .position(|q| q.queue_flags.graphics) + .position(|q| q.queue_flags.intersects(crate::device::QueueFlags::GRAPHICS)) .map(|i| (p, i as u32)) }) .min_by_key(|(p, _)| {