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

* Use actual integer bitflags for Vulkan bitflag types

* Fix doc tests

* Fix Fence and Semaphore on Win32 and Fuchsia

* Add macro for bitflags that have a corresponding enum

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

View File

@ -23,6 +23,7 @@ use vulkano::{
},
device::{
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,
)

View File

@ -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()

View File

@ -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()

View File

@ -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");

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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(),
)

View File

@ -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()

View File

@ -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,
)

View File

@ -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),
)

View File

@ -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),
)

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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<DrawIndirectCommand> = 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<Vertex> = CpuBufferPool::new(
memory_allocator,
BufferUsage {
storage_buffer: true,
vertex_buffer: true,
..BufferUsage::empty()
},
BufferUsage::STORAGE_BUFFER | BufferUsage::VERTEX_BUFFER,
MemoryUsage::Upload,
);

View File

@ -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,
)

View File

@ -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(),
)

View File

@ -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

View File

@ -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,
)

View File

@ -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),
)

View File

@ -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()
},

View File

@ -47,10 +47,7 @@ fn rand_grid(
) -> Arc<CpuAccessibleBuffer<[u32]>> {
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();

View File

@ -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(),
)

View File

@ -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),
)

View File

@ -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,
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
// 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.
with_availability: false,
..QueryResultFlags::empty()
},
// | 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(),
)

View File

@ -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 {

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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();

View File

@ -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,
)

View File

@ -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::<vs::ty::Data>::new(
memory_allocator.clone(),
BufferUsage {
uniform_buffer: true,
..BufferUsage::empty()
},
BufferUsage::UNIFORM_BUFFER,
MemoryUsage::Upload,
);

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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)|*
}
};

View File

@ -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();

View File

@ -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::<Vec<usize>>();
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);
}

View File

@ -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<DeviceSize> {
pub fn block_size(self) -> Option<DeviceSize> {
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<CompressionType> {
pub fn compression(self) -> Option<CompressionType> {
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<NumericType> {
pub fn type_color(self) -> Option<NumericType> {
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<NumericType> {
pub fn type_depth(self) -> Option<NumericType> {
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<NumericType> {
pub fn type_stencil(self) -> Option<NumericType> {
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<ChromaSampling> {
pub fn ycbcr_chroma_sampling(self) -> Option<ChromaSampling> {
match self {
#(#ycbcr_chroma_sampling_items)*
_ => None,

View File

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

View File

@ -63,7 +63,7 @@ enum Enable {
#[derive(Clone, Debug, PartialEq)]
enum PropertyValue {
Bool,
BoolMember(Ident),
BoolMember(Vec<Ident>),
}
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 {

View File

@ -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(),
)

View File

@ -216,14 +216,7 @@ where
///
/// - Panics if `T` has zero size.
pub fn upload(allocator: Arc<A>) -> CpuBufferPool<T, A> {
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<A>) -> CpuBufferPool<T, A> {
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<A>) -> CpuBufferPool<T, A> {
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<A>) -> CpuBufferPool<T, A> {
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<A>) -> CpuBufferPool<T, A> {
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()

View File

@ -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,23 +548,13 @@ 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,
)
let destination =
CpuAccessibleBuffer::from_data(&memory_allocator, BufferUsage::TRANSFER_DST, false, 0)
.unwrap();
command_buffer_builder
@ -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();

View File

@ -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],
},

View File

@ -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()
},
)

View File

@ -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);
}

View File

@ -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],
},
*/

View File

@ -26,15 +26,10 @@
//!
//! # let queue: Arc<vulkano::device::Queue> = 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<Format>;
/// Returns the features supported by the buffer view's format.
fn format_features(&self) -> &FormatFeatures;
fn format_features(&self) -> FormatFeatures;
/// Returns the byte range of the wrapped buffer that this view exposes.
fn range(&self) -> Range<DeviceSize>;
@ -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<DeviceSize> {
@ -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,

View File

@ -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(),
)

View File

@ -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<Ib, I>(&mut self, index_buffer: Arc<Ib>) -> &mut Self
where
Ib: TypedBufferAccess<Content = [I]> + '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);
}

View File

@ -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<L, A> AutoCommandBufferBuilder<L, A>
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);
}

View File

@ -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"],

View File

@ -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,

View File

@ -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<dyn ImageViewAbstract>| {
// 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,

View File

@ -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<D, T>(
&mut self,
query_pool: Arc<QueryPool>,
@ -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::<T>() 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::<T>() as DeviceSize == 0);
debug_assert!(stride % size_of::<T>() as DeviceSize == 0);

View File

@ -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,15 +1716,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 {
color_attachment_read: true,
color_attachment_write: true,
..AccessFlags::empty()
}, // 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,
@ -1724,15 +1738,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 {
color_attachment_read: true,
color_attachment_write: true,
..AccessFlags::empty()
}, // 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,
@ -1762,15 +1770,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,
@ -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,15 +1824,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,
@ -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<dyn ImageViewAbstract>) -> 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<dyn ImageViewAbstract>) -> 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

View File

@ -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()

View File

@ -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();

View File

@ -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,21 +415,22 @@ 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 {
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.iter().count() != 1 {
if subresource.aspects.count() != 1 {
return Err(CopyError::MultipleAspectsNotAllowed {
resource,
region_index,
@ -423,12 +438,12 @@ where
});
}
if subresource.aspects.plane0 {
if subresource.aspects.intersects(ImageAspects::PLANE_0) {
(
image.format().planes()[0],
image.dimensions().width_height_depth(),
)
} else if subresource.aspects.plane1 {
} else if subresource.aspects.intersects(ImageAspects::PLANE_1) {
(
image.format().planes()[1],
image
@ -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,13 +1091,14 @@ where
});
}
let (image_subresource_format, image_subresource_extent) = if image_aspects.plane0 {
if image_subresource.aspects.plane0 {
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.plane1 {
} else if image_subresource.aspects.intersects(ImageAspects::PLANE_1) {
(
dst_image.format().planes()[1],
dst_image
@ -1222,9 +1244,10 @@ 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 {
let image_subresource_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 image_subresource_format {
Format::D16_UNORM | Format::D16_UNORM_S8_UINT => 2,
Format::D32_SFLOAT
@ -1250,15 +1273,17 @@ where
});
}
let buffer_offset_alignment = if image_aspects.depth || image_aspects.stencil {
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 !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS | QueueFlags::COMPUTE)
{
if buffer_offset_alignment % 2 != 0 {
buffer_offset_alignment *= 2;
@ -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,13 +1519,14 @@ where
});
}
let (image_subresource_format, image_subresource_extent) = if image_aspects.plane0 {
if image_subresource.aspects.plane0 {
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.plane1 {
} else if image_subresource.aspects.intersects(ImageAspects::PLANE_1) {
(
src_image.format().planes()[1],
src_image
@ -1646,9 +1672,10 @@ 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 {
let image_subresource_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 image_subresource_format {
Format::D16_UNORM | Format::D16_UNORM_S8_UINT => 2,
Format::D32_SFLOAT
@ -1674,15 +1701,17 @@ where
});
}
let buffer_offset_alignment = if image_aspects.depth || image_aspects.stencil {
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 !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS | QueueFlags::COMPUTE)
{
if buffer_offset_alignment % 2 != 0 {
buffer_offset_alignment *= 2;
@ -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

View File

@ -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<Semaphore>) -> Self {
Self {
semaphore,
stages: PipelineStages {
all_commands: true,
..PipelineStages::empty()
},
stages: PipelineStages::ALL_COMMANDS,
_ne: crate::NonExhaustive(()),
}
}

View File

@ -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"],

View File

@ -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,

View File

@ -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,
)

View File

@ -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;
}
}

View File

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

View File

@ -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.

View File

@ -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(),

View File

@ -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,8 +941,9 @@ impl PhysicalDevice {
let format = format.unwrap();
let aspects = format.aspects();
let has_separate_stencil_usage =
if stencil_usage.is_empty() || !(aspects.depth && aspects.stencil) {
let has_separate_stencil_usage = if stencil_usage.is_empty()
|| !aspects.contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
{
stencil_usage = usage;
false
} else {
@ -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

View File

@ -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<ash::vk::QueueFamilyProperties> 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],
},
}

View File

@ -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],
},
}

View File

@ -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<Item = ImageAspect> {
let Self {
color,
depth,
stencil,
metadata,
plane0,
plane1,
plane2,
memory_plane0,
memory_plane1,
memory_plane2,
_ne: _,
} = *self;
[
color.then_some(ImageAspect::Color),
depth.then_some(ImageAspect::Depth),
stencil.then_some(ImageAspect::Stencil),
metadata.then_some(ImageAspect::Metadata),
plane0.then_some(ImageAspect::Plane0),
plane1.then_some(ImageAspect::Plane1),
plane2.then_some(ImageAspect::Plane2),
memory_plane0.then_some(ImageAspect::MemoryPlane0),
memory_plane1.then_some(ImageAspect::MemoryPlane1),
memory_plane2.then_some(ImageAspect::MemoryPlane2),
]
.into_iter()
.flatten()
}
}
impl From<ImageAspect> for ImageAspects {
#[inline]
fn from(aspect: ImageAspect) -> Self {
let mut result = Self::empty();
match aspect {
ImageAspect::Color => result.color = true,
ImageAspect::Depth => result.depth = true,
ImageAspect::Stencil => result.stencil = true,
ImageAspect::Metadata => result.metadata = true,
ImageAspect::Plane0 => result.plane0 = true,
ImageAspect::Plane1 => result.plane1 = true,
ImageAspect::Plane2 => result.plane2 = true,
ImageAspect::MemoryPlane0 => result.memory_plane0 = true,
ImageAspect::MemoryPlane1 => result.memory_plane1 = true,
ImageAspect::MemoryPlane2 => result.memory_plane2 = true,
}
result
}
}
impl FromIterator<ImageAspect> for ImageAspects {
fn from_iter<T: IntoIterator<Item = ImageAspect>>(iter: T) -> Self {
let mut result = Self::empty();
for aspect in iter {
match aspect {
ImageAspect::Color => result.color = true,
ImageAspect::Depth => result.depth = true,
ImageAspect::Stencil => result.stencil = true,
ImageAspect::Metadata => result.metadata = true,
ImageAspect::Plane0 => result.plane0 = true,
ImageAspect::Plane1 => result.plane1 = true,
ImageAspect::Plane2 => result.plane2 = true,
ImageAspect::MemoryPlane0 => result.memory_plane0 = true,
ImageAspect::MemoryPlane1 => result.memory_plane1 = true,
ImageAspect::MemoryPlane2 => result.memory_plane2 = true,
}
}
result
}
}

View File

@ -10,8 +10,8 @@
use super::{
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<Arc<AttachmentImage>, 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<Arc<AttachmentImage>, 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<Arc<AttachmentImage>, 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<Arc<AttachmentImage>, 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<Arc<AttachmentImage>, 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<Arc<AttachmentImage>, 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<Arc<AttachmentImage>, 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<Arc<AttachmentImage>, 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<Arc<AttachmentImage>, 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<Arc<AttachmentImage>, 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<Arc<AttachmentImage>, 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<Arc<AttachmentImage>, 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

View File

@ -115,7 +115,7 @@ impl ImmutableImage {
) -> Result<(Arc<ImmutableImage>, Arc<ImmutableImageInitialization>), 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,11 +239,12 @@ 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;

View File

@ -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.

View File

@ -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<u32> for SampleCount {
@ -273,63 +300,6 @@ impl TryFrom<u32> for SampleCount {
}
}
vulkan_bitflags! {
/// Specifies a set of [`SampleCount`] values.
#[non_exhaustive]
SampleCounts = SampleCountFlags(u32);
/// 1 sample per pixel.
sample1 = TYPE_1,
/// 2 samples per pixel.
sample2 = TYPE_2,
/// 4 samples per pixel.
sample4 = TYPE_4,
/// 8 samples per pixel.
sample8 = TYPE_8,
/// 16 samples per pixel.
sample16 = TYPE_16,
/// 32 samples per pixel.
sample32 = TYPE_32,
/// 64 samples per pixel.
sample64 = TYPE_64,
}
impl SampleCounts {
/// Returns true if `self` has the `sample_count` value set.
#[inline]
pub const fn contains_count(&self, sample_count: SampleCount) -> bool {
match sample_count {
SampleCount::Sample1 => self.sample1,
SampleCount::Sample2 => self.sample2,
SampleCount::Sample4 => self.sample4,
SampleCount::Sample8 => self.sample8,
SampleCount::Sample16 => self.sample16,
SampleCount::Sample32 => self.sample32,
SampleCount::Sample64 => self.sample64,
}
}
/// Returns the maximum sample count supported by `self`.
#[inline]
pub const fn max_count(&self) -> SampleCount {
match self {
Self { sample64: true, .. } => SampleCount::Sample64,
Self { sample32: true, .. } => SampleCount::Sample32,
Self { sample16: true, .. } => SampleCount::Sample16,
Self { sample8: true, .. } => SampleCount::Sample8,
Self { sample4: true, .. } => SampleCount::Sample4,
Self { sample2: true, .. } => SampleCount::Sample2,
_ => SampleCount::Sample1,
}
}
}
/// Specifies how many mipmaps must be allocated.
///
/// Note that at least one mipmap must be allocated, to store the main level of the image.
@ -358,8 +328,9 @@ impl From<u32> for MipmapsCount {
}
vulkan_enum! {
// 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.

View File

@ -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,21 +51,21 @@ impl StorageImage {
queue_family_indices: impl IntoIterator<Item = u32>,
) -> Result<Arc<StorageImage>, 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();
@ -89,7 +89,7 @@ impl StorageImage {
queue_family_indices: impl IntoIterator<Item = u32>,
) -> Result<Arc<StorageImage>, 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<Item = u32>,
) -> Result<Arc<StorageImage>, 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,

View File

@ -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,8 +141,9 @@ 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) {
let has_separate_stencil_usage = if stencil_usage.is_empty()
|| !aspects.contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
{
stencil_usage = usage;
false
} else {
@ -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
}
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
}
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,8 +874,9 @@ 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) {
let has_separate_stencil_usage = if stencil_usage.is_empty()
|| !aspects.contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
{
stencil_usage = usage;
false
} else {
@ -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::<SmallVec<[usize; 4]>>()
.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,14 +3439,11 @@ 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()
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,
},

View File

@ -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(),
}

View File

@ -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],
},
*/

View File

@ -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!(!subresource_range.aspects.intersects(
ImageAspects::METADATA
| ImageAspects::MEMORY_PLANE_0
| ImageAspects::MEMORY_PLANE_1
| ImageAspects::MEMORY_PLANE_2
));
assert!({
let num_bits = color as u8
+ depth as u8
+ stencil as u8
+ plane0 as u8
+ plane1 as u8
+ plane2 as u8;
num_bits == 1 || depth && stencil && !(color || plane0 || plane1 || plane2)
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,30 +728,36 @@ 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
if format.shader_storage_image_without_format() {
if device
.enabled_features()
.shader_storage_image_read_without_format,
storage_write_without_format: is_without_format
&& device
.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
.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.
pub fn image(&self) -> &Arc<I> {
&self.image
@ -1146,9 +1160,38 @@ impl From<RequirementNotMet> 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<Handle = ash::vk::ImageView> + DeviceOwned + Debug + Send + Sync
@ -1254,7 +1268,7 @@ pub unsafe trait ImageViewAbstract:
fn format(&self) -> Option<Format>;
/// Returns the features supported by the image view's format.
fn format_features(&self) -> &FormatFeatures;
fn format_features(&self) -> FormatFeatures;
/// Returns the sampler YCbCr conversion that this image view was created with, if any.
fn sampler_ycbcr_conversion(&self) -> Option<&Arc<SamplerYcbcrConversion>>;
@ -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<SamplerYcbcrConversion>> {
@ -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<dyn ImageAccess> {
}
#[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<dyn ImageAccess> {
}
#[inline]
fn usage(&self) -> &ImageUsage {
&self.usage
fn usage(&self) -> ImageUsage {
self.usage
}
#[inline]

View File

@ -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(|_| {}))
},
)

View File

@ -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()

View File

@ -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,

View File

@ -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<ash::vk::$ty_ffi> 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,42 +428,53 @@ 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<ash::vk::$ty_ffi> for $ty {
#[inline]
fn from(#[allow(unused_variables)] val: ash::vk::$ty_ffi) -> Self {
Self {
$(
$flag_name: val.intersects(ash::vk::$ty_ffi::$flag_name_ffi),
)*
_ne: crate::NonExhaustive(()),
}
}
$( $($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<ash::vk::$ty_ffi> for $ty {
#[inline]
fn from(val: ash::vk::$ty_ffi) -> Self {
Self(val.as_raw() & Self::all_raw())
}
}
impl std::ops::BitAnd for $ty {
@ -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<T>(iter: T) -> Self where T: IntoIterator<Item = $ty_enum> {
iter.into_iter().map(|item| Self::from(item)).fold(Self::empty(), |r, i| r.union(i))
}
}
impl IntoIterator for $ty_bitflags {
type Item = $ty_enum;
type IntoIter = std::iter::Flatten<
std::array::IntoIter<
Option<Self::Item>,
{ $ty_bitflags::all_raw().count_ones() as usize },
>
>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
[
$(
self.intersects(Self::$flag_name_bitflags)
.then_some($ty_enum::$flag_name_enum),
)*
].into_iter().flatten()
}
}
}
}
pub(crate) use {vulkan_bitflags, vulkan_bitflags_enum, vulkan_enum};

View File

@ -353,17 +353,17 @@ impl From<MemoryUsage> for MemoryTypeFilter {
match usage {
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<S: Suballocator> GenericMemoryAllocator<S> {
&& 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<S: Suballocator> GenericMemoryAllocator<S> {
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<S: Suballocator> GenericMemoryAllocator<S> {
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<S: Suballocator> MemoryAllocator for GenericMemoryAllocator<S> {
/// # 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<S: Suballocator> MemoryAllocator for GenericMemoryAllocator<S> {
/// - Returns [`SuballocatorBlockSizeExceeded`] if `S` is `PoolAllocator<BLOCK_SIZE>` 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<S: Suballocator> MemoryAllocator for GenericMemoryAllocator<S> {
/// `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

View File

@ -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,7 +124,8 @@ impl MemoryAlloc {
None
};
let atom_size = (property_flags.host_visible && !property_flags.host_coherent)
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);
@ -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<DeviceSize>) -> 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<DeviceSize>) -> 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<vulkano::device::Device> = return;
///
@ -620,7 +621,7 @@ unsafe impl DeviceOwned for MemoryAlloc {
/// // requirements, instead of picking the first one that satisfies them. Also, you have to
/// // 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;
///

View File

@ -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<DeviceSize, DeviceMemoryError> {
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<ExternalMemoryHandleType> for ExternalMemoryHandleTypes {
#[inline]
fn from(val: ExternalMemoryHandleType) -> Self {
let mut result = Self::empty();
match val {
ExternalMemoryHandleType::OpaqueFd => result.opaque_fd = true,
ExternalMemoryHandleType::OpaqueWin32 => result.opaque_win32 = true,
ExternalMemoryHandleType::OpaqueWin32Kmt => result.opaque_win32_kmt = true,
ExternalMemoryHandleType::D3D11Texture => result.d3d11_texture = true,
ExternalMemoryHandleType::D3D11TextureKmt => result.d3d11_texture_kmt = true,
ExternalMemoryHandleType::D3D12Heap => result.d3d12_heap = true,
ExternalMemoryHandleType::D3D12Resource => result.d3d12_resource = true,
ExternalMemoryHandleType::DmaBuf => result.dma_buf = true,
ExternalMemoryHandleType::AndroidHardwareBuffer => {
result.android_hardware_buffer = true
}
ExternalMemoryHandleType::HostAllocation => result.host_allocation = true,
ExternalMemoryHandleType::HostMappedForeignMemory => {
result.host_mapped_foreign_memory = true
}
ExternalMemoryHandleType::ZirconVmo => result.zircon_vmo = true,
ExternalMemoryHandleType::RdmaAddress => result.rdma_address = true,
}
result
}
}
impl ExternalMemoryHandleTypes {
/// Returns an iterator of `ExternalMemoryHandleType` enum values, representing the fields that
/// are set in `self`.
#[inline]
pub fn iter(&self) -> impl Iterator<Item = ExternalMemoryHandleType> {
let ExternalMemoryHandleTypes {
opaque_fd,
opaque_win32,
opaque_win32_kmt,
d3d11_texture,
d3d11_texture_kmt,
d3d12_heap,
d3d12_resource,
dma_buf,
android_hardware_buffer,
host_allocation,
host_mapped_foreign_memory,
zircon_vmo,
rdma_address,
_ne: _,
} = *self;
[
opaque_fd.then_some(ExternalMemoryHandleType::OpaqueFd),
opaque_win32.then_some(ExternalMemoryHandleType::OpaqueWin32),
opaque_win32_kmt.then_some(ExternalMemoryHandleType::OpaqueWin32Kmt),
d3d11_texture.then_some(ExternalMemoryHandleType::D3D11Texture),
d3d11_texture_kmt.then_some(ExternalMemoryHandleType::D3D11TextureKmt),
d3d12_heap.then_some(ExternalMemoryHandleType::D3D12Heap),
d3d12_resource.then_some(ExternalMemoryHandleType::D3D12Resource),
dma_buf.then_some(ExternalMemoryHandleType::DmaBuf),
android_hardware_buffer.then_some(ExternalMemoryHandleType::AndroidHardwareBuffer),
host_allocation.then_some(ExternalMemoryHandleType::HostAllocation),
host_mapped_foreign_memory.then_some(ExternalMemoryHandleType::HostMappedForeignMemory),
zircon_vmo.then_some(ExternalMemoryHandleType::HostMappedForeignMemory),
rdma_address.then_some(ExternalMemoryHandleType::HostMappedForeignMemory),
]
.into_iter()
.flatten()
}
}
vulkan_bitflags! {
/// A mask specifying flags for device memory allocation.
#[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<RequirementNotMet> for DeviceMemoryError {
/// # Examples
///
/// ```
/// use vulkano::memory::{DeviceMemory, MappedDeviceMemory, MemoryAllocateInfo};
/// use vulkano::memory::{DeviceMemory, MappedDeviceMemory, MemoryAllocateInfo, MemoryPropertyFlags};
///
/// # let device: std::sync::Arc<vulkano::device::Device> = return;
/// // The memory type must be mappable.
@ -1268,7 +1159,7 @@ impl From<RequirementNotMet> 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<OomError> 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]

View File

@ -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],
},

View File

@ -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,
)

View File

@ -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()
@ -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()

View File

@ -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<AttachmentBlend> 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,
}

View File

@ -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.

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