mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2024-11-25 00:04:15 +00:00
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:
parent
05746e8f75
commit
a984a925c4
@ -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,
|
||||
)
|
||||
|
@ -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()
|
||||
|
@ -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()
|
||||
|
@ -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");
|
||||
|
@ -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,
|
||||
)
|
||||
|
@ -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,
|
||||
)
|
||||
|
@ -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,
|
||||
)
|
||||
|
@ -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(),
|
||||
)
|
||||
|
@ -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()
|
||||
|
@ -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,
|
||||
)
|
||||
|
@ -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),
|
||||
)
|
||||
|
@ -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),
|
||||
)
|
||||
|
@ -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,
|
||||
)
|
||||
|
@ -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,
|
||||
)
|
||||
|
@ -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,
|
||||
)
|
||||
|
@ -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,
|
||||
)
|
||||
|
@ -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,
|
||||
);
|
||||
|
||||
|
@ -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,
|
||||
)
|
||||
|
@ -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(),
|
||||
)
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
)
|
||||
|
@ -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),
|
||||
)
|
||||
|
@ -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()
|
||||
},
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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(),
|
||||
)
|
||||
|
@ -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),
|
||||
)
|
||||
|
@ -21,6 +21,7 @@ use vulkano::{
|
||||
},
|
||||
device::{
|
||||
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
||||
QueueFlags,
|
||||
},
|
||||
format::Format,
|
||||
image::{view::ImageView, AttachmentImage, ImageAccess, ImageUsage, SwapchainImage},
|
||||
@ -84,7 +85,8 @@ fn main() {
|
||||
.iter()
|
||||
.enumerate()
|
||||
.position(|(i, q)| {
|
||||
q.queue_flags.graphics && p.surface_support(i as u32, &surface).unwrap_or(false)
|
||||
q.queue_flags.intersects(QueueFlags::GRAPHICS)
|
||||
&& p.surface_support(i as u32, &surface).unwrap_or(false)
|
||||
})
|
||||
.map(|i| (p, i as u32))
|
||||
})
|
||||
@ -139,13 +141,10 @@ fn main() {
|
||||
min_image_count: surface_capabilities.min_image_count,
|
||||
image_format,
|
||||
image_extent: window.inner_size().into(),
|
||||
image_usage: ImageUsage {
|
||||
color_attachment: true,
|
||||
..ImageUsage::empty()
|
||||
},
|
||||
image_usage: ImageUsage::COLOR_ATTACHMENT,
|
||||
composite_alpha: surface_capabilities
|
||||
.supported_composite_alpha
|
||||
.iter()
|
||||
.into_iter()
|
||||
.next()
|
||||
.unwrap(),
|
||||
..Default::default()
|
||||
@ -212,10 +211,7 @@ fn main() {
|
||||
];
|
||||
let vertex_buffer = CpuAccessibleBuffer::from_iter(
|
||||
&memory_allocator,
|
||||
BufferUsage {
|
||||
vertex_buffer: true,
|
||||
..BufferUsage::empty()
|
||||
},
|
||||
BufferUsage::VERTEX_BUFFER,
|
||||
false,
|
||||
vertices,
|
||||
)
|
||||
@ -421,15 +417,13 @@ fn main() {
|
||||
)
|
||||
.unwrap()
|
||||
// Begin query 0, then draw the red triangle.
|
||||
// Enabling the `precise` bit would give exact numeric results. This needs
|
||||
// the `occlusion_query_precise` feature to be enabled on the device.
|
||||
// Enabling the `QueryControlFlags::PRECISE` flag would give exact numeric
|
||||
// results. This needs the `occlusion_query_precise` feature to be enabled on
|
||||
// the device.
|
||||
.begin_query(
|
||||
query_pool.clone(),
|
||||
0,
|
||||
QueryControlFlags {
|
||||
precise: false,
|
||||
..QueryControlFlags::empty()
|
||||
},
|
||||
QueryControlFlags::empty(), // QueryControlFlags::PRECISE
|
||||
)
|
||||
.unwrap()
|
||||
.bind_vertex_buffers(0, triangle1.clone())
|
||||
@ -439,14 +433,7 @@ fn main() {
|
||||
.end_query(query_pool.clone(), 0)
|
||||
.unwrap()
|
||||
// Begin query 1 for the cyan triangle.
|
||||
.begin_query(
|
||||
query_pool.clone(),
|
||||
1,
|
||||
QueryControlFlags {
|
||||
precise: false,
|
||||
..QueryControlFlags::empty()
|
||||
},
|
||||
)
|
||||
.begin_query(query_pool.clone(), 1, QueryControlFlags::empty())
|
||||
.unwrap()
|
||||
.bind_vertex_buffers(0, triangle2.clone())
|
||||
.draw(triangle2.len() as u32, 1, 0, 0)
|
||||
@ -454,14 +441,7 @@ fn main() {
|
||||
.end_query(query_pool.clone(), 1)
|
||||
.unwrap()
|
||||
// Finally, query 2 for the green triangle.
|
||||
.begin_query(
|
||||
query_pool.clone(),
|
||||
2,
|
||||
QueryControlFlags {
|
||||
precise: false,
|
||||
..QueryControlFlags::empty()
|
||||
},
|
||||
)
|
||||
.begin_query(query_pool.clone(), 2, QueryControlFlags::empty())
|
||||
.unwrap()
|
||||
.bind_vertex_buffers(0, triangle3.clone())
|
||||
.draw(triangle3.len() as u32, 1, 0, 0)
|
||||
@ -505,30 +485,29 @@ fn main() {
|
||||
// `copy_query_pool_results` function on a command buffer to write results to a
|
||||
// Vulkano buffer. This could then be used to influence draw operations further down
|
||||
// the line, either in the same frame or a future frame.
|
||||
#[rustfmt::skip]
|
||||
query_pool
|
||||
.queries_range(0..3)
|
||||
.unwrap()
|
||||
.get_results(
|
||||
&mut query_results,
|
||||
QueryResultFlags {
|
||||
// Block the function call until the results are available.
|
||||
// Note: if not all the queries have actually been executed, then this
|
||||
// will wait forever for something that never happens!
|
||||
wait: true,
|
||||
// Block the function call until the results are available.
|
||||
// Note: if not all the queries have actually been executed, then this
|
||||
// will wait forever for something that never happens!
|
||||
QueryResultFlags::WAIT
|
||||
|
||||
// Blocking and waiting will never give partial results.
|
||||
partial: false,
|
||||
// Enable this flag to give partial results if available, instead of waiting
|
||||
// for the full results.
|
||||
// | QueryResultFlags::PARTIAL
|
||||
|
||||
// Blocking and waiting will ensure the results are always available after
|
||||
// the function returns.
|
||||
//
|
||||
// If you disable waiting, then this can be used to include the
|
||||
// availability of each query's results. You need one extra element per
|
||||
// query in your `query_results` buffer for this. This element will
|
||||
// be filled with a zero/nonzero value indicating availability.
|
||||
with_availability: false,
|
||||
..QueryResultFlags::empty()
|
||||
},
|
||||
// Blocking and waiting will ensure the results are always available after
|
||||
// the function returns.
|
||||
//
|
||||
// If you disable waiting, then this flag can be enabled to include the
|
||||
// availability of each query's results. You need one extra element per
|
||||
// query in your `query_results` buffer for this. This element will
|
||||
// be filled with a zero/nonzero value indicating availability.
|
||||
// | QueryResultFlags::WITH_AVAILABILITY
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
@ -564,11 +543,7 @@ fn window_size_dependent_setup(
|
||||
memory_allocator,
|
||||
dimensions,
|
||||
Format::D16_UNORM,
|
||||
ImageUsage {
|
||||
depth_stencil_attachment: true,
|
||||
transient_attachment: true,
|
||||
..ImageUsage::empty()
|
||||
},
|
||||
ImageUsage::DEPTH_STENCIL_ATTACHMENT | ImageUsage::TRANSIENT_ATTACHMENT,
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
)
|
||||
|
@ -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,
|
||||
)
|
||||
|
@ -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,
|
||||
)
|
||||
|
@ -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,
|
||||
)
|
||||
|
@ -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,
|
||||
)
|
||||
|
@ -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,
|
||||
)
|
||||
|
@ -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,
|
||||
)
|
||||
|
@ -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();
|
||||
|
@ -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,
|
||||
)
|
||||
|
@ -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,
|
||||
);
|
||||
|
||||
|
@ -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,
|
||||
)
|
||||
|
@ -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,
|
||||
)
|
||||
|
@ -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,
|
||||
)
|
||||
|
@ -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,
|
||||
)
|
||||
|
@ -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)|*
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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") {
|
||||
|
@ -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 {
|
||||
|
@ -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(),
|
||||
)
|
||||
|
@ -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()
|
||||
|
@ -83,7 +83,8 @@ use std::{
|
||||
/// // Create a CPU accessible buffer initialized with the data.
|
||||
/// let temporary_accessible_buffer = CpuAccessibleBuffer::from_iter(
|
||||
/// &memory_allocator,
|
||||
/// BufferUsage { transfer_src: true, ..BufferUsage::empty() }, // Specify this buffer will be used as a transfer source.
|
||||
/// // Specify this buffer will be used as a transfer source.
|
||||
/// BufferUsage::TRANSFER_SRC,
|
||||
/// false,
|
||||
/// data,
|
||||
/// )
|
||||
@ -93,11 +94,8 @@ use std::{
|
||||
/// let device_local_buffer = DeviceLocalBuffer::<[f32]>::array(
|
||||
/// &memory_allocator,
|
||||
/// 10_000 as vulkano::DeviceSize,
|
||||
/// BufferUsage {
|
||||
/// storage_buffer: true,
|
||||
/// transfer_dst: true,
|
||||
/// ..BufferUsage::empty()
|
||||
/// }, // Specify use as a storage buffer and transfer destination.
|
||||
/// // Specify use as a storage buffer and transfer destination.
|
||||
/// BufferUsage::STORAGE_BUFFER | BufferUsage::TRANSFER_DST,
|
||||
/// device.active_queue_family_indices().iter().copied(),
|
||||
/// )
|
||||
/// .unwrap();
|
||||
@ -182,10 +180,7 @@ where
|
||||
{
|
||||
unsafe {
|
||||
// We automatically set `transfer_dst` to true in order to avoid annoying errors.
|
||||
let actual_usage = BufferUsage {
|
||||
transfer_dst: true,
|
||||
..usage
|
||||
};
|
||||
let actual_usage = usage | BufferUsage::TRANSFER_DST;
|
||||
|
||||
let buffer = DeviceLocalBuffer::raw(
|
||||
allocator,
|
||||
@ -229,15 +224,8 @@ where
|
||||
where
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
let source = CpuAccessibleBuffer::from_data(
|
||||
allocator,
|
||||
BufferUsage {
|
||||
transfer_src: true,
|
||||
..BufferUsage::empty()
|
||||
},
|
||||
false,
|
||||
data,
|
||||
)?;
|
||||
let source =
|
||||
CpuAccessibleBuffer::from_data(allocator, BufferUsage::TRANSFER_SRC, false, data)?;
|
||||
DeviceLocalBuffer::from_buffer(allocator, source, usage, command_buffer_builder)
|
||||
}
|
||||
}
|
||||
@ -267,15 +255,8 @@ where
|
||||
D::IntoIter: ExactSizeIterator,
|
||||
A: CommandBufferAllocator,
|
||||
{
|
||||
let source = CpuAccessibleBuffer::from_iter(
|
||||
allocator,
|
||||
BufferUsage {
|
||||
transfer_src: true,
|
||||
..BufferUsage::empty()
|
||||
},
|
||||
false,
|
||||
data,
|
||||
)?;
|
||||
let source =
|
||||
CpuAccessibleBuffer::from_iter(allocator, BufferUsage::TRANSFER_SRC, false, data)?;
|
||||
DeviceLocalBuffer::from_buffer(allocator, source, usage, command_buffer_builder)
|
||||
}
|
||||
}
|
||||
@ -407,10 +388,7 @@ where
|
||||
// VUID-VkMemoryAllocateInfo-pNext-00639
|
||||
// Guaranteed because we always create a dedicated allocation
|
||||
|
||||
let external_memory_handle_types = ExternalMemoryHandleTypes {
|
||||
opaque_fd: true,
|
||||
..ExternalMemoryHandleTypes::empty()
|
||||
};
|
||||
let external_memory_handle_types = ExternalMemoryHandleTypes::OPAQUE_FD;
|
||||
let raw_buffer = RawBuffer::new(
|
||||
allocator.device().clone(),
|
||||
BufferCreateInfo {
|
||||
@ -570,24 +548,14 @@ mod tests {
|
||||
let buffer = DeviceLocalBuffer::from_data(
|
||||
&memory_allocator,
|
||||
12u32,
|
||||
BufferUsage {
|
||||
transfer_src: true,
|
||||
..BufferUsage::empty()
|
||||
},
|
||||
BufferUsage::TRANSFER_SRC,
|
||||
&mut command_buffer_builder,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let destination = CpuAccessibleBuffer::from_data(
|
||||
&memory_allocator,
|
||||
BufferUsage {
|
||||
transfer_dst: true,
|
||||
..BufferUsage::empty()
|
||||
},
|
||||
false,
|
||||
0,
|
||||
)
|
||||
.unwrap();
|
||||
let destination =
|
||||
CpuAccessibleBuffer::from_data(&memory_allocator, BufferUsage::TRANSFER_DST, false, 0)
|
||||
.unwrap();
|
||||
|
||||
command_buffer_builder
|
||||
.copy_buffer(CopyBufferInfo::buffers(buffer, destination.clone()))
|
||||
@ -621,20 +589,14 @@ mod tests {
|
||||
let buffer = DeviceLocalBuffer::from_iter(
|
||||
&allocator,
|
||||
(0..512u32).map(|n| n * 2),
|
||||
BufferUsage {
|
||||
transfer_src: true,
|
||||
..BufferUsage::empty()
|
||||
},
|
||||
BufferUsage::TRANSFER_SRC,
|
||||
&mut command_buffer_builder,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let destination = CpuAccessibleBuffer::from_iter(
|
||||
&allocator,
|
||||
BufferUsage {
|
||||
transfer_dst: true,
|
||||
..BufferUsage::empty()
|
||||
},
|
||||
BufferUsage::TRANSFER_DST,
|
||||
false,
|
||||
(0..512).map(|_| 0u32),
|
||||
)
|
||||
@ -676,10 +638,7 @@ mod tests {
|
||||
DeviceLocalBuffer::from_data(
|
||||
&allocator,
|
||||
(),
|
||||
BufferUsage {
|
||||
transfer_dst: true,
|
||||
..BufferUsage::empty()
|
||||
},
|
||||
BufferUsage::TRANSFER_DST,
|
||||
&mut command_buffer_builder,
|
||||
)
|
||||
.unwrap();
|
||||
|
@ -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],
|
||||
},
|
||||
|
@ -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()
|
||||
},
|
||||
)
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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],
|
||||
},
|
||||
*/
|
||||
|
@ -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,
|
||||
|
@ -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(),
|
||||
)
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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"],
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
||||
|
@ -18,9 +18,9 @@ use crate::{
|
||||
sys::UnsafeCommandBufferBuilder,
|
||||
AutoCommandBufferBuilder, SubpassContents,
|
||||
},
|
||||
device::DeviceOwned,
|
||||
device::{DeviceOwned, QueueFlags},
|
||||
format::{ClearColorValue, ClearValue, Format, NumericType},
|
||||
image::{ImageLayout, ImageViewAbstract, SampleCount},
|
||||
image::{ImageAspects, ImageLayout, ImageUsage, ImageViewAbstract, SampleCount},
|
||||
render_pass::{
|
||||
AttachmentDescription, Framebuffer, LoadOp, RenderPass, ResolveMode, StoreOp,
|
||||
SubpassDescription,
|
||||
@ -103,7 +103,10 @@ where
|
||||
let queue_family_properties = self.queue_family_properties();
|
||||
|
||||
// VUID-vkCmdBeginRenderPass2-commandBuffer-cmdpool
|
||||
if !queue_family_properties.queue_flags.graphics {
|
||||
if !queue_family_properties
|
||||
.queue_flags
|
||||
.intersects(QueueFlags::GRAPHICS)
|
||||
{
|
||||
return Err(RenderPassError::NotSupportedByQueueFamily);
|
||||
}
|
||||
|
||||
@ -155,7 +158,7 @@ where
|
||||
match layout {
|
||||
ImageLayout::ColorAttachmentOptimal => {
|
||||
// VUID-vkCmdBeginRenderPass2-initialLayout-03094
|
||||
if !image_view.usage().color_attachment {
|
||||
if !image_view.usage().intersects(ImageUsage::COLOR_ATTACHMENT) {
|
||||
return Err(RenderPassError::AttachmentImageMissingUsage {
|
||||
attachment_index,
|
||||
usage: "color_attachment",
|
||||
@ -167,7 +170,10 @@ where
|
||||
| ImageLayout::DepthStencilAttachmentOptimal
|
||||
| ImageLayout::DepthStencilReadOnlyOptimal => {
|
||||
// VUID-vkCmdBeginRenderPass2-initialLayout-03096
|
||||
if !image_view.usage().depth_stencil_attachment {
|
||||
if !image_view
|
||||
.usage()
|
||||
.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
|
||||
{
|
||||
return Err(RenderPassError::AttachmentImageMissingUsage {
|
||||
attachment_index,
|
||||
usage: "depth_stencil_attachment",
|
||||
@ -176,7 +182,10 @@ where
|
||||
}
|
||||
ImageLayout::ShaderReadOnlyOptimal => {
|
||||
// VUID-vkCmdBeginRenderPass2-initialLayout-03097
|
||||
if !(image_view.usage().sampled || image_view.usage().input_attachment) {
|
||||
if !image_view
|
||||
.usage()
|
||||
.intersects(ImageUsage::SAMPLED | ImageUsage::INPUT_ATTACHMENT)
|
||||
{
|
||||
return Err(RenderPassError::AttachmentImageMissingUsage {
|
||||
attachment_index,
|
||||
usage: "sampled or input_attachment",
|
||||
@ -185,7 +194,7 @@ where
|
||||
}
|
||||
ImageLayout::TransferSrcOptimal => {
|
||||
// VUID-vkCmdBeginRenderPass2-initialLayout-03098
|
||||
if !image_view.usage().transfer_src {
|
||||
if !image_view.usage().intersects(ImageUsage::TRANSFER_SRC) {
|
||||
return Err(RenderPassError::AttachmentImageMissingUsage {
|
||||
attachment_index,
|
||||
usage: "transfer_src",
|
||||
@ -194,7 +203,7 @@ where
|
||||
}
|
||||
ImageLayout::TransferDstOptimal => {
|
||||
// VUID-vkCmdBeginRenderPass2-initialLayout-03099
|
||||
if !image_view.usage().transfer_dst {
|
||||
if !image_view.usage().intersects(ImageUsage::TRANSFER_DST) {
|
||||
return Err(RenderPassError::AttachmentImageMissingUsage {
|
||||
attachment_index,
|
||||
usage: "transfer_dst",
|
||||
@ -228,7 +237,7 @@ where
|
||||
match atch_ref.layout {
|
||||
ImageLayout::ColorAttachmentOptimal => {
|
||||
// VUID-vkCmdBeginRenderPass2-initialLayout-03094
|
||||
if !image_view.usage().color_attachment {
|
||||
if !image_view.usage().intersects(ImageUsage::COLOR_ATTACHMENT) {
|
||||
return Err(RenderPassError::AttachmentImageMissingUsage {
|
||||
attachment_index: atch_ref.attachment,
|
||||
usage: "color_attachment",
|
||||
@ -240,7 +249,10 @@ where
|
||||
| ImageLayout::DepthStencilAttachmentOptimal
|
||||
| ImageLayout::DepthStencilReadOnlyOptimal => {
|
||||
// VUID-vkCmdBeginRenderPass2-initialLayout-03096
|
||||
if !image_view.usage().depth_stencil_attachment {
|
||||
if !image_view
|
||||
.usage()
|
||||
.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
|
||||
{
|
||||
return Err(RenderPassError::AttachmentImageMissingUsage {
|
||||
attachment_index: atch_ref.attachment,
|
||||
usage: "depth_stencil_attachment",
|
||||
@ -249,7 +261,10 @@ where
|
||||
}
|
||||
ImageLayout::ShaderReadOnlyOptimal => {
|
||||
// VUID-vkCmdBeginRenderPass2-initialLayout-03097
|
||||
if !(image_view.usage().sampled || image_view.usage().input_attachment) {
|
||||
if !image_view
|
||||
.usage()
|
||||
.intersects(ImageUsage::SAMPLED | ImageUsage::INPUT_ATTACHMENT)
|
||||
{
|
||||
return Err(RenderPassError::AttachmentImageMissingUsage {
|
||||
attachment_index: atch_ref.attachment,
|
||||
usage: "sampled or input_attachment",
|
||||
@ -258,7 +273,7 @@ where
|
||||
}
|
||||
ImageLayout::TransferSrcOptimal => {
|
||||
// VUID-vkCmdBeginRenderPass2-initialLayout-03098
|
||||
if !image_view.usage().transfer_src {
|
||||
if !image_view.usage().intersects(ImageUsage::TRANSFER_SRC) {
|
||||
return Err(RenderPassError::AttachmentImageMissingUsage {
|
||||
attachment_index: atch_ref.attachment,
|
||||
usage: "transfer_src",
|
||||
@ -267,7 +282,7 @@ where
|
||||
}
|
||||
ImageLayout::TransferDstOptimal => {
|
||||
// VUID-vkCmdBeginRenderPass2-initialLayout-03099
|
||||
if !image_view.usage().transfer_dst {
|
||||
if !image_view.usage().intersects(ImageUsage::TRANSFER_DST) {
|
||||
return Err(RenderPassError::AttachmentImageMissingUsage {
|
||||
attachment_index: atch_ref.attachment,
|
||||
usage: "transfer_dst",
|
||||
@ -344,9 +359,9 @@ where
|
||||
}
|
||||
} else {
|
||||
let attachment_aspects = attachment_format.aspects();
|
||||
let need_depth =
|
||||
attachment_aspects.depth && attachment_desc.load_op == LoadOp::Clear;
|
||||
let need_stencil = attachment_aspects.stencil
|
||||
let need_depth = attachment_aspects.intersects(ImageAspects::DEPTH)
|
||||
&& attachment_desc.load_op == LoadOp::Clear;
|
||||
let need_stencil = attachment_aspects.intersects(ImageAspects::STENCIL)
|
||||
&& attachment_desc.stencil_load_op == LoadOp::Clear;
|
||||
|
||||
if need_depth && need_stencil {
|
||||
@ -456,10 +471,10 @@ where
|
||||
}
|
||||
|
||||
// VUID-vkCmdNextSubpass2-commandBuffer-cmdpool
|
||||
debug_assert!({
|
||||
let queue_family_properties = self.queue_family_properties();
|
||||
queue_family_properties.queue_flags.graphics
|
||||
});
|
||||
debug_assert!(self
|
||||
.queue_family_properties()
|
||||
.queue_flags
|
||||
.intersects(QueueFlags::GRAPHICS));
|
||||
|
||||
// VUID-vkCmdNextSubpass2-bufferlevel
|
||||
// Ensured by the type of the impl block
|
||||
@ -514,10 +529,10 @@ where
|
||||
}
|
||||
|
||||
// VUID-vkCmdEndRenderPass2-commandBuffer-cmdpool
|
||||
debug_assert!({
|
||||
let queue_family_properties = self.queue_family_properties();
|
||||
queue_family_properties.queue_flags.graphics
|
||||
});
|
||||
debug_assert!(self
|
||||
.queue_family_properties()
|
||||
.queue_flags
|
||||
.intersects(QueueFlags::GRAPHICS));
|
||||
|
||||
// VUID-vkCmdEndRenderPass2-bufferlevel
|
||||
// Ensured by the type of the impl block
|
||||
@ -678,7 +693,7 @@ where
|
||||
// VUID-vkCmdBeginRendering-dynamicRendering-06446
|
||||
if !device.enabled_features().dynamic_rendering {
|
||||
return Err(RenderPassError::RequirementNotMet {
|
||||
required_for: "`begin_rendering`",
|
||||
required_for: "`AutoCommandBufferBuilder::begin_rendering`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
features: &["dynamic_rendering"],
|
||||
..Default::default()
|
||||
@ -689,7 +704,10 @@ where
|
||||
let queue_family_properties = self.queue_family_properties();
|
||||
|
||||
// VUID-vkCmdBeginRendering-commandBuffer-cmdpool
|
||||
if !queue_family_properties.queue_flags.graphics {
|
||||
if !queue_family_properties
|
||||
.queue_flags
|
||||
.intersects(QueueFlags::GRAPHICS)
|
||||
{
|
||||
return Err(RenderPassError::NotSupportedByQueueFamily);
|
||||
}
|
||||
|
||||
@ -785,7 +803,7 @@ where
|
||||
store_op.validate_device(device)?;
|
||||
|
||||
// VUID-VkRenderingInfo-colorAttachmentCount-06087
|
||||
if !image_view.usage().color_attachment {
|
||||
if !image_view.usage().intersects(ImageUsage::COLOR_ATTACHMENT) {
|
||||
return Err(RenderPassError::ColorAttachmentMissingUsage { attachment_index });
|
||||
}
|
||||
|
||||
@ -942,12 +960,15 @@ where
|
||||
let image_aspects = image_view.format().unwrap().aspects();
|
||||
|
||||
// VUID-VkRenderingInfo-pDepthAttachment-06547
|
||||
if !image_aspects.depth {
|
||||
if !image_aspects.intersects(ImageAspects::DEPTH) {
|
||||
return Err(RenderPassError::DepthAttachmentFormatUsageNotSupported);
|
||||
}
|
||||
|
||||
// VUID-VkRenderingInfo-pDepthAttachment-06088
|
||||
if !image_view.usage().depth_stencil_attachment {
|
||||
if !image_view
|
||||
.usage()
|
||||
.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
|
||||
{
|
||||
return Err(RenderPassError::DepthAttachmentMissingUsage);
|
||||
}
|
||||
|
||||
@ -1003,7 +1024,7 @@ where
|
||||
// VUID-VkRenderingInfo-pDepthAttachment-06102
|
||||
if !properties
|
||||
.supported_depth_resolve_modes
|
||||
.map_or(false, |modes| modes.contains_mode(mode))
|
||||
.map_or(false, |modes| modes.contains_enum(mode))
|
||||
{
|
||||
return Err(RenderPassError::DepthAttachmentResolveModeNotSupported);
|
||||
}
|
||||
@ -1069,12 +1090,15 @@ where
|
||||
let image_aspects = image_view.format().unwrap().aspects();
|
||||
|
||||
// VUID-VkRenderingInfo-pStencilAttachment-06548
|
||||
if !image_aspects.stencil {
|
||||
if !image_aspects.intersects(ImageAspects::STENCIL) {
|
||||
return Err(RenderPassError::StencilAttachmentFormatUsageNotSupported);
|
||||
}
|
||||
|
||||
// VUID-VkRenderingInfo-pStencilAttachment-06089
|
||||
if !image_view.usage().depth_stencil_attachment {
|
||||
if !image_view
|
||||
.usage()
|
||||
.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
|
||||
{
|
||||
return Err(RenderPassError::StencilAttachmentMissingUsage);
|
||||
}
|
||||
|
||||
@ -1130,7 +1154,7 @@ where
|
||||
// VUID-VkRenderingInfo-pStencilAttachment-06103
|
||||
if !properties
|
||||
.supported_stencil_resolve_modes
|
||||
.map_or(false, |modes| modes.contains_mode(mode))
|
||||
.map_or(false, |modes| modes.contains_enum(mode))
|
||||
{
|
||||
return Err(RenderPassError::StencilAttachmentResolveModeNotSupported);
|
||||
}
|
||||
@ -1251,10 +1275,10 @@ where
|
||||
}
|
||||
|
||||
// VUID-vkCmdEndRendering-commandBuffer-cmdpool
|
||||
debug_assert!({
|
||||
let queue_family_properties = self.queue_family_properties();
|
||||
queue_family_properties.queue_flags.graphics
|
||||
});
|
||||
debug_assert!(self
|
||||
.queue_family_properties()
|
||||
.queue_flags
|
||||
.intersects(QueueFlags::GRAPHICS));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -1416,8 +1440,9 @@ where
|
||||
if matches!(
|
||||
clear_attachment,
|
||||
ClearAttachment::Depth(_) | ClearAttachment::DepthStencil(_)
|
||||
) && !depth_format.map_or(false, |format| format.aspects().depth)
|
||||
{
|
||||
) && !depth_format.map_or(false, |format| {
|
||||
format.aspects().intersects(ImageAspects::DEPTH)
|
||||
}) {
|
||||
return Err(RenderPassError::ClearAttachmentNotCompatible {
|
||||
clear_attachment,
|
||||
attachment_format: None,
|
||||
@ -1428,8 +1453,9 @@ where
|
||||
if matches!(
|
||||
clear_attachment,
|
||||
ClearAttachment::Stencil(_) | ClearAttachment::DepthStencil(_)
|
||||
) && !stencil_format.map_or(false, |format| format.aspects().stencil)
|
||||
{
|
||||
) && !stencil_format.map_or(false, |format| {
|
||||
format.aspects().intersects(ImageAspects::STENCIL)
|
||||
}) {
|
||||
return Err(RenderPassError::ClearAttachmentNotCompatible {
|
||||
clear_attachment,
|
||||
attachment_format: None,
|
||||
@ -1502,10 +1528,10 @@ where
|
||||
}
|
||||
|
||||
// VUID-vkCmdClearAttachments-commandBuffer-cmdpool
|
||||
debug_assert!({
|
||||
let queue_family_properties = self.queue_family_properties();
|
||||
queue_family_properties.queue_flags.graphics
|
||||
});
|
||||
debug_assert!(self
|
||||
.queue_family_properties()
|
||||
.queue_flags
|
||||
.intersects(QueueFlags::GRAPHICS));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -1559,18 +1585,12 @@ impl SyncCommandBufferBuilder {
|
||||
image: image_view.image(),
|
||||
subresource_range: image_view.subresource_range().clone(),
|
||||
memory: PipelineMemoryAccess {
|
||||
stages: PipelineStages {
|
||||
all_commands: true,
|
||||
..PipelineStages::empty()
|
||||
}, // TODO: wrong!
|
||||
access: AccessFlags {
|
||||
input_attachment_read: true,
|
||||
color_attachment_read: true,
|
||||
color_attachment_write: true,
|
||||
depth_stencil_attachment_read: true,
|
||||
depth_stencil_attachment_write: true,
|
||||
..AccessFlags::empty()
|
||||
}, // TODO: suboptimal
|
||||
stages: PipelineStages::ALL_COMMANDS, // TODO: wrong!
|
||||
access: AccessFlags::INPUT_ATTACHMENT_READ
|
||||
| AccessFlags::COLOR_ATTACHMENT_READ
|
||||
| AccessFlags::COLOR_ATTACHMENT_WRITE
|
||||
| AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ
|
||||
| AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE, // TODO: suboptimal
|
||||
exclusive: true, // TODO: suboptimal ; note: remember to always pass true if desc.initial_layout != desc.final_layout
|
||||
},
|
||||
start_layout: desc.initial_layout,
|
||||
@ -1696,16 +1716,10 @@ impl SyncCommandBufferBuilder {
|
||||
image: image_view.image(),
|
||||
subresource_range: image_view.subresource_range().clone(),
|
||||
memory: PipelineMemoryAccess {
|
||||
stages: PipelineStages {
|
||||
all_commands: true,
|
||||
..PipelineStages::empty()
|
||||
}, // TODO: wrong!
|
||||
access: AccessFlags {
|
||||
color_attachment_read: true,
|
||||
color_attachment_write: true,
|
||||
..AccessFlags::empty()
|
||||
}, // TODO: suboptimal
|
||||
exclusive: true, // TODO: suboptimal
|
||||
stages: PipelineStages::ALL_COMMANDS, // TODO: wrong!
|
||||
access: AccessFlags::COLOR_ATTACHMENT_READ
|
||||
| AccessFlags::COLOR_ATTACHMENT_WRITE, // TODO: suboptimal
|
||||
exclusive: true, // TODO: suboptimal
|
||||
},
|
||||
start_layout: image_layout,
|
||||
end_layout: image_layout,
|
||||
@ -1724,16 +1738,10 @@ impl SyncCommandBufferBuilder {
|
||||
image: image_view.image(),
|
||||
subresource_range: image_view.subresource_range().clone(),
|
||||
memory: PipelineMemoryAccess {
|
||||
stages: PipelineStages {
|
||||
all_commands: true,
|
||||
..PipelineStages::empty()
|
||||
}, // TODO: wrong!
|
||||
access: AccessFlags {
|
||||
color_attachment_read: true,
|
||||
color_attachment_write: true,
|
||||
..AccessFlags::empty()
|
||||
}, // TODO: suboptimal
|
||||
exclusive: true, // TODO: suboptimal
|
||||
stages: PipelineStages::ALL_COMMANDS, // TODO: wrong!
|
||||
access: AccessFlags::COLOR_ATTACHMENT_READ
|
||||
| AccessFlags::COLOR_ATTACHMENT_WRITE, // TODO: suboptimal
|
||||
exclusive: true, // TODO: suboptimal
|
||||
},
|
||||
start_layout: image_layout,
|
||||
end_layout: image_layout,
|
||||
@ -1762,16 +1770,10 @@ impl SyncCommandBufferBuilder {
|
||||
image: image_view.image(),
|
||||
subresource_range: image_view.subresource_range().clone(),
|
||||
memory: PipelineMemoryAccess {
|
||||
stages: PipelineStages {
|
||||
all_commands: true,
|
||||
..PipelineStages::empty()
|
||||
}, // TODO: wrong!
|
||||
access: AccessFlags {
|
||||
depth_stencil_attachment_read: true,
|
||||
depth_stencil_attachment_write: true,
|
||||
..AccessFlags::empty()
|
||||
}, // TODO: suboptimal
|
||||
exclusive: true, // TODO: suboptimal
|
||||
stages: PipelineStages::ALL_COMMANDS, // TODO: wrong!
|
||||
access: AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ
|
||||
| AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE, // TODO: suboptimal
|
||||
exclusive: true, // TODO: suboptimal
|
||||
},
|
||||
start_layout: image_layout,
|
||||
end_layout: image_layout,
|
||||
@ -1790,15 +1792,9 @@ impl SyncCommandBufferBuilder {
|
||||
image: image_view.image(),
|
||||
subresource_range: image_view.subresource_range().clone(),
|
||||
memory: PipelineMemoryAccess {
|
||||
stages: PipelineStages {
|
||||
all_commands: true,
|
||||
..PipelineStages::empty()
|
||||
}, // TODO: wrong!
|
||||
access: AccessFlags {
|
||||
depth_stencil_attachment_read: true,
|
||||
depth_stencil_attachment_write: true,
|
||||
..AccessFlags::empty()
|
||||
}, // TODO: suboptimal
|
||||
stages: PipelineStages::ALL_COMMANDS, // TODO: wrong!
|
||||
access: AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ
|
||||
| AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE, // TODO: suboptimal
|
||||
exclusive: true, // TODO: suboptimal
|
||||
},
|
||||
start_layout: image_layout,
|
||||
@ -1828,16 +1824,10 @@ impl SyncCommandBufferBuilder {
|
||||
image: image_view.image(),
|
||||
subresource_range: image_view.subresource_range().clone(),
|
||||
memory: PipelineMemoryAccess {
|
||||
stages: PipelineStages {
|
||||
all_commands: true,
|
||||
..PipelineStages::empty()
|
||||
}, // TODO: wrong!
|
||||
access: AccessFlags {
|
||||
depth_stencil_attachment_read: true,
|
||||
depth_stencil_attachment_write: true,
|
||||
..AccessFlags::empty()
|
||||
}, // TODO: suboptimal
|
||||
exclusive: true, // TODO: suboptimal
|
||||
stages: PipelineStages::ALL_COMMANDS, // TODO: wrong!
|
||||
access: AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ
|
||||
| AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE, // TODO: suboptimal
|
||||
exclusive: true, // TODO: suboptimal
|
||||
},
|
||||
start_layout: image_layout,
|
||||
end_layout: image_layout,
|
||||
@ -1856,15 +1846,9 @@ impl SyncCommandBufferBuilder {
|
||||
image: image_view.image(),
|
||||
subresource_range: image_view.subresource_range().clone(),
|
||||
memory: PipelineMemoryAccess {
|
||||
stages: PipelineStages {
|
||||
all_commands: true,
|
||||
..PipelineStages::empty()
|
||||
}, // TODO: wrong!
|
||||
access: AccessFlags {
|
||||
depth_stencil_attachment_read: true,
|
||||
depth_stencil_attachment_write: true,
|
||||
..AccessFlags::empty()
|
||||
}, // TODO: suboptimal
|
||||
stages: PipelineStages::ALL_COMMANDS, // TODO: wrong!
|
||||
access: AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ
|
||||
| AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE, // TODO: suboptimal
|
||||
exclusive: true, // TODO: suboptimal
|
||||
},
|
||||
start_layout: image_layout,
|
||||
@ -2429,7 +2413,7 @@ impl RenderingAttachmentInfo {
|
||||
#[inline]
|
||||
pub fn image_view(image_view: Arc<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
|
||||
|
@ -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()
|
||||
|
@ -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();
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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(()),
|
||||
}
|
||||
}
|
||||
|
@ -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"],
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
)
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -335,11 +335,8 @@ where
|
||||
.into_iter()
|
||||
.map(|semaphore| {
|
||||
SemaphoreSubmitInfo {
|
||||
stages: PipelineStages {
|
||||
// TODO: correct stages ; hard
|
||||
all_commands: true,
|
||||
..PipelineStages::empty()
|
||||
},
|
||||
// TODO: correct stages ; hard
|
||||
stages: PipelineStages::ALL_COMMANDS,
|
||||
..SemaphoreSubmitInfo::semaphore(semaphore)
|
||||
}
|
||||
})
|
||||
|
@ -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.
|
||||
|
@ -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(),
|
||||
|
@ -14,15 +14,15 @@ use crate::{
|
||||
device::{properties::Properties, DeviceExtensions, Features, FeaturesFfi, PropertiesFfi},
|
||||
format::{Format, FormatProperties},
|
||||
image::{
|
||||
ImageFormatInfo, ImageFormatProperties, ImageUsage, SparseImageFormatInfo,
|
||||
ImageAspects, ImageFormatInfo, ImageFormatProperties, ImageUsage, SparseImageFormatInfo,
|
||||
SparseImageFormatProperties,
|
||||
},
|
||||
instance::Instance,
|
||||
macros::{vulkan_bitflags, vulkan_enum},
|
||||
memory::MemoryProperties,
|
||||
swapchain::{
|
||||
ColorSpace, FullScreenExclusive, PresentMode, SupportedSurfaceTransforms, Surface,
|
||||
SurfaceApi, SurfaceCapabilities, SurfaceInfo,
|
||||
ColorSpace, FullScreenExclusive, PresentMode, Surface, SurfaceApi, SurfaceCapabilities,
|
||||
SurfaceInfo, SurfaceTransforms,
|
||||
},
|
||||
sync::{
|
||||
ExternalFenceInfo, ExternalFenceProperties, ExternalSemaphoreInfo,
|
||||
@ -442,7 +442,7 @@ impl PhysicalDevice {
|
||||
) -> Result<(), PhysicalDeviceError> {
|
||||
if !self.instance.enabled_extensions().ext_directfb_surface {
|
||||
return Err(PhysicalDeviceError::RequirementNotMet {
|
||||
required_for: "`directfb_presentation_support`",
|
||||
required_for: "`PhysicalDevice::directfb_presentation_support`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
instance_extensions: &["ext_directfb_surface"],
|
||||
..Default::default()
|
||||
@ -510,7 +510,7 @@ impl PhysicalDevice {
|
||||
.khr_external_memory_capabilities)
|
||||
{
|
||||
return Err(PhysicalDeviceError::RequirementNotMet {
|
||||
required_for: "`external_buffer_properties`",
|
||||
required_for: "`PhysicalDevice::external_buffer_properties`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
api_version: Some(Version::V1_1),
|
||||
instance_extensions: &["khr_external_memory_capabilities"],
|
||||
@ -623,7 +623,7 @@ impl PhysicalDevice {
|
||||
.khr_external_fence_capabilities)
|
||||
{
|
||||
return Err(PhysicalDeviceError::RequirementNotMet {
|
||||
required_for: "`external_fence_properties`",
|
||||
required_for: "`PhysicalDevice::external_fence_properties`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
api_version: Some(Version::V1_1),
|
||||
instance_extensions: &["khr_external_fence_capabilities"],
|
||||
@ -731,7 +731,7 @@ impl PhysicalDevice {
|
||||
.khr_external_semaphore_capabilities)
|
||||
{
|
||||
return Err(PhysicalDeviceError::RequirementNotMet {
|
||||
required_for: "`external_semaphore_properties`",
|
||||
required_for: "`PhysicalDevice::external_semaphore_properties`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
api_version: Some(Version::V1_1),
|
||||
instance_extensions: &["khr_external_semaphore_capabilities"],
|
||||
@ -941,13 +941,14 @@ impl PhysicalDevice {
|
||||
let format = format.unwrap();
|
||||
let aspects = format.aspects();
|
||||
|
||||
let has_separate_stencil_usage =
|
||||
if stencil_usage.is_empty() || !(aspects.depth && aspects.stencil) {
|
||||
stencil_usage = usage;
|
||||
false
|
||||
} else {
|
||||
stencil_usage == usage
|
||||
};
|
||||
let has_separate_stencil_usage = if stencil_usage.is_empty()
|
||||
|| !aspects.contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
|
||||
{
|
||||
stencil_usage = usage;
|
||||
false
|
||||
} else {
|
||||
stencil_usage == usage
|
||||
};
|
||||
|
||||
// VUID-VkPhysicalDeviceImageFormatInfo2-format-parameter
|
||||
format.validate_physical_device(self)?;
|
||||
@ -969,7 +970,8 @@ impl PhysicalDevice {
|
||||
|| self.supported_extensions().ext_separate_stencil_usage)
|
||||
{
|
||||
return Err(PhysicalDeviceError::RequirementNotMet {
|
||||
required_for: "`image_format_info.stencil_usage` is `Some` and `image_format_info.format` has both a depth and a stencil aspect",
|
||||
required_for: "`image_format_info.stencil_usage` is `Some` and \
|
||||
`image_format_info.format` has both a depth and a stencil aspect",
|
||||
requires_one_of: RequiresOneOf {
|
||||
api_version: Some(Version::V1_2),
|
||||
device_extensions: &["ext_separate_stencil_usage"],
|
||||
@ -1040,7 +1042,9 @@ impl PhysicalDevice {
|
||||
|
||||
let aspects = format.unwrap().aspects();
|
||||
|
||||
if stencil_usage.is_empty() || !(aspects.depth && aspects.stencil) {
|
||||
if stencil_usage.is_empty()
|
||||
|| !aspects.contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
|
||||
{
|
||||
*stencil_usage = *usage;
|
||||
}
|
||||
}
|
||||
@ -1213,7 +1217,7 @@ impl PhysicalDevice {
|
||||
) -> Result<(), PhysicalDeviceError> {
|
||||
if !self.instance.enabled_extensions().qnx_screen_surface {
|
||||
return Err(PhysicalDeviceError::RequirementNotMet {
|
||||
required_for: "`qnx_screen_presentation_support`",
|
||||
required_for: "`PhysicalDevice::qnx_screen_presentation_support`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
instance_extensions: &["qnx_screen_surface"],
|
||||
..Default::default()
|
||||
@ -1486,7 +1490,7 @@ impl PhysicalDevice {
|
||||
|| self.instance.enabled_extensions().khr_surface)
|
||||
{
|
||||
return Err(PhysicalDeviceError::RequirementNotMet {
|
||||
required_for: "`surface_capabilities`",
|
||||
required_for: "`PhysicalDevice::surface_capabilities`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
instance_extensions: &["khr_get_surface_capabilities2", "khr_surface"],
|
||||
..Default::default()
|
||||
@ -1655,10 +1659,10 @@ impl PhysicalDevice {
|
||||
.supported_transforms
|
||||
.into(),
|
||||
|
||||
current_transform: SupportedSurfaceTransforms::from(
|
||||
current_transform: SurfaceTransforms::from(
|
||||
capabilities_vk.surface_capabilities.current_transform,
|
||||
)
|
||||
.iter()
|
||||
.into_iter()
|
||||
.next()
|
||||
.unwrap(), // TODO:
|
||||
supported_composite_alpha: capabilities_vk
|
||||
@ -1668,7 +1672,7 @@ impl PhysicalDevice {
|
||||
supported_usage_flags: {
|
||||
let usage =
|
||||
ImageUsage::from(capabilities_vk.surface_capabilities.supported_usage_flags);
|
||||
debug_assert!(usage.color_attachment); // specs say that this must be true
|
||||
debug_assert!(usage.intersects(ImageUsage::COLOR_ATTACHMENT)); // specs say that this must be true
|
||||
usage
|
||||
},
|
||||
|
||||
@ -1711,7 +1715,7 @@ impl PhysicalDevice {
|
||||
|| self.instance.enabled_extensions().khr_surface)
|
||||
{
|
||||
return Err(PhysicalDeviceError::RequirementNotMet {
|
||||
required_for: "`surface_formats`",
|
||||
required_for: "`PhysicalDevice::surface_formats`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
instance_extensions: &["khr_get_surface_capabilities2", "khr_surface"],
|
||||
..Default::default()
|
||||
@ -1928,7 +1932,7 @@ impl PhysicalDevice {
|
||||
fn validate_surface_present_modes(&self, surface: &Surface) -> Result<(), PhysicalDeviceError> {
|
||||
if !self.instance.enabled_extensions().khr_surface {
|
||||
return Err(PhysicalDeviceError::RequirementNotMet {
|
||||
required_for: "`surface_present_modes`",
|
||||
required_for: "`PhysicalDevice::surface_present_modes`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
instance_extensions: &["khr_surface"],
|
||||
..Default::default()
|
||||
@ -2022,7 +2026,7 @@ impl PhysicalDevice {
|
||||
) -> Result<(), PhysicalDeviceError> {
|
||||
if !self.instance.enabled_extensions().khr_surface {
|
||||
return Err(PhysicalDeviceError::RequirementNotMet {
|
||||
required_for: "`surface_support`",
|
||||
required_for: "`PhysicalDevice::surface_support`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
instance_extensions: &["khr_surface"],
|
||||
..Default::default()
|
||||
@ -2084,7 +2088,7 @@ impl PhysicalDevice {
|
||||
fn validate_tool_properties(&self) -> Result<(), PhysicalDeviceError> {
|
||||
if !(self.api_version() >= Version::V1_3 || self.supported_extensions().ext_tooling_info) {
|
||||
return Err(PhysicalDeviceError::RequirementNotMet {
|
||||
required_for: "`tooling_properties`",
|
||||
required_for: "`PhysicalDevice::tooling_properties`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
api_version: Some(Version::V1_3),
|
||||
device_extensions: &["ext_tooling_info"],
|
||||
@ -2195,7 +2199,7 @@ impl PhysicalDevice {
|
||||
) -> Result<(), PhysicalDeviceError> {
|
||||
if !self.instance.enabled_extensions().khr_wayland_surface {
|
||||
return Err(PhysicalDeviceError::RequirementNotMet {
|
||||
required_for: "`wayland_presentation_support`",
|
||||
required_for: "`PhysicalDevice::wayland_presentation_support`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
instance_extensions: &["khr_wayland_surface"],
|
||||
..Default::default()
|
||||
@ -2250,7 +2254,7 @@ impl PhysicalDevice {
|
||||
) -> Result<(), PhysicalDeviceError> {
|
||||
if !self.instance.enabled_extensions().khr_win32_surface {
|
||||
return Err(PhysicalDeviceError::RequirementNotMet {
|
||||
required_for: "`win32_presentation_support`",
|
||||
required_for: "`PhysicalDevice::win32_presentation_support`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
instance_extensions: &["khr_win32_surface"],
|
||||
..Default::default()
|
||||
@ -2304,7 +2308,7 @@ impl PhysicalDevice {
|
||||
) -> Result<(), PhysicalDeviceError> {
|
||||
if !self.instance.enabled_extensions().khr_xcb_surface {
|
||||
return Err(PhysicalDeviceError::RequirementNotMet {
|
||||
required_for: "`xcb_presentation_support`",
|
||||
required_for: "`PhysicalDevice::xcb_presentation_support`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
instance_extensions: &["khr_xcb_surface"],
|
||||
..Default::default()
|
||||
@ -2368,7 +2372,7 @@ impl PhysicalDevice {
|
||||
) -> Result<(), PhysicalDeviceError> {
|
||||
if !self.instance.enabled_extensions().khr_xlib_surface {
|
||||
return Err(PhysicalDeviceError::RequirementNotMet {
|
||||
required_for: "`xlib_presentation_support`",
|
||||
required_for: "`PhysicalDevice::xlib_presentation_support`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
instance_extensions: &["khr_xlib_surface"],
|
||||
..Default::default()
|
||||
@ -2420,8 +2424,9 @@ unsafe impl VulkanObject for PhysicalDevice {
|
||||
crate::impl_id_counter!(PhysicalDevice);
|
||||
|
||||
vulkan_enum! {
|
||||
/// Type of a physical device.
|
||||
#[non_exhaustive]
|
||||
|
||||
/// Type of a physical device.
|
||||
PhysicalDeviceType = PhysicalDeviceType(i32);
|
||||
|
||||
/// The device is an integrated GPU.
|
||||
@ -2482,8 +2487,9 @@ impl Display for ConformanceVersion {
|
||||
}
|
||||
|
||||
vulkan_enum! {
|
||||
/// An identifier for the driver of a physical device.
|
||||
#[non_exhaustive]
|
||||
|
||||
/// An identifier for the driver of a physical device.
|
||||
DriverId = DriverId(i32);
|
||||
|
||||
// TODO: document
|
||||
@ -2550,78 +2556,81 @@ pub struct ToolProperties {
|
||||
}
|
||||
|
||||
vulkan_bitflags! {
|
||||
/// The purpose of an active tool.
|
||||
#[non_exhaustive]
|
||||
|
||||
/// The purpose of an active tool.
|
||||
ToolPurposes = ToolPurposeFlags(u32);
|
||||
|
||||
/// The tool provides validation of API usage.
|
||||
validation = VALIDATION,
|
||||
VALIDATION = VALIDATION,
|
||||
|
||||
/// The tool provides profiling of API usage.
|
||||
profiling = PROFILING,
|
||||
PROFILING = PROFILING,
|
||||
|
||||
/// The tool is capturing data about the application's API usage.
|
||||
tracing = TRACING,
|
||||
TRACING = TRACING,
|
||||
|
||||
/// The tool provides additional API features or extensions on top of the underlying
|
||||
/// implementation.
|
||||
additional_features = ADDITIONAL_FEATURES,
|
||||
ADDITIONAL_FEATURES = ADDITIONAL_FEATURES,
|
||||
|
||||
/// The tool modifies the API features, limits or extensions presented to the application.
|
||||
modifying_features = MODIFYING_FEATURES,
|
||||
MODIFYING_FEATURES = MODIFYING_FEATURES,
|
||||
|
||||
/// The tool reports information to the user via a
|
||||
/// [`DebugUtilsMessenger`](crate::instance::debug::DebugUtilsMessenger).
|
||||
debug_reporting = DEBUG_REPORTING_EXT {
|
||||
DEBUG_REPORTING = DEBUG_REPORTING_EXT {
|
||||
instance_extensions: [ext_debug_utils, ext_debug_report],
|
||||
},
|
||||
|
||||
/// The tool consumes debug markers or object debug annotation, queue labels or command buffer
|
||||
/// labels.
|
||||
debug_markers = DEBUG_MARKERS_EXT {
|
||||
DEBUG_MARKERS = DEBUG_MARKERS_EXT {
|
||||
device_extensions: [ext_debug_marker],
|
||||
instance_extensions: [ext_debug_utils],
|
||||
},
|
||||
}
|
||||
|
||||
vulkan_bitflags! {
|
||||
/// Specifies which subgroup operations are supported.
|
||||
#[non_exhaustive]
|
||||
|
||||
/// Specifies which subgroup operations are supported.
|
||||
SubgroupFeatures = SubgroupFeatureFlags(u32);
|
||||
|
||||
// TODO: document
|
||||
basic = BASIC,
|
||||
BASIC = BASIC,
|
||||
|
||||
// TODO: document
|
||||
vote = VOTE,
|
||||
VOTE = VOTE,
|
||||
|
||||
// TODO: document
|
||||
arithmetic = ARITHMETIC,
|
||||
ARITHMETIC = ARITHMETIC,
|
||||
|
||||
// TODO: document
|
||||
ballot = BALLOT,
|
||||
BALLOT = BALLOT,
|
||||
|
||||
// TODO: document
|
||||
shuffle = SHUFFLE,
|
||||
SHUFFLE = SHUFFLE,
|
||||
|
||||
// TODO: document
|
||||
shuffle_relative = SHUFFLE_RELATIVE,
|
||||
SHUFFLE_RELATIVE = SHUFFLE_RELATIVE,
|
||||
|
||||
// TODO: document
|
||||
clustered = CLUSTERED,
|
||||
CLUSTERED = CLUSTERED,
|
||||
|
||||
// TODO: document
|
||||
quad = QUAD,
|
||||
QUAD = QUAD,
|
||||
|
||||
// TODO: document
|
||||
partitioned = PARTITIONED_NV {
|
||||
PARTITIONED = PARTITIONED_NV {
|
||||
device_extensions: [nv_shader_subgroup_partitioned],
|
||||
},
|
||||
}
|
||||
|
||||
vulkan_enum! {
|
||||
/// Specifies how the device clips single point primitives.
|
||||
#[non_exhaustive]
|
||||
|
||||
/// Specifies how the device clips single point primitives.
|
||||
PointClippingBehavior = PointClippingBehavior(i32);
|
||||
|
||||
/// Points are clipped if they lie outside any clip plane, both those bounding the view volume
|
||||
@ -2633,8 +2642,9 @@ vulkan_enum! {
|
||||
}
|
||||
|
||||
vulkan_enum! {
|
||||
/// Specifies whether, and how, shader float controls can be set independently.
|
||||
#[non_exhaustive]
|
||||
|
||||
/// Specifies whether, and how, shader float controls can be set independently.
|
||||
ShaderFloatControlsIndependence = ShaderFloatControlsIndependence(i32);
|
||||
|
||||
// TODO: document
|
||||
|
@ -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],
|
||||
},
|
||||
}
|
||||
|
@ -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],
|
||||
},
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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,12 +239,13 @@ impl ImmutableImage {
|
||||
}
|
||||
|
||||
let need_to_generate_mipmaps = has_mipmaps(mip_levels);
|
||||
let usage = ImageUsage {
|
||||
transfer_dst: true,
|
||||
transfer_src: need_to_generate_mipmaps,
|
||||
sampled: true,
|
||||
..ImageUsage::empty()
|
||||
};
|
||||
let usage = ImageUsage::TRANSFER_DST
|
||||
| ImageUsage::SAMPLED
|
||||
| if need_to_generate_mipmaps {
|
||||
ImageUsage::TRANSFER_SRC
|
||||
} else {
|
||||
ImageUsage::empty()
|
||||
};
|
||||
let flags = ImageCreateFlags::empty();
|
||||
let layout = ImageLayout::ShaderReadOnlyOptimal;
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -10,8 +10,8 @@
|
||||
use super::{
|
||||
sys::{Image, ImageMemory, RawImage},
|
||||
traits::ImageContent,
|
||||
ImageAccess, ImageCreateFlags, ImageDescriptorLayouts, ImageDimensions, ImageError, ImageInner,
|
||||
ImageLayout, ImageUsage,
|
||||
ImageAccess, ImageAspects, ImageCreateFlags, ImageDescriptorLayouts, ImageDimensions,
|
||||
ImageError, ImageInner, ImageLayout, ImageUsage,
|
||||
};
|
||||
use crate::{
|
||||
device::{Device, DeviceOwned, Queue},
|
||||
@ -51,22 +51,22 @@ impl StorageImage {
|
||||
queue_family_indices: impl IntoIterator<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();
|
||||
|
||||
StorageImage::with_usage(
|
||||
@ -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,
|
||||
|
@ -29,7 +29,8 @@ use crate::{
|
||||
},
|
||||
memory::{
|
||||
allocator::{AllocationCreationError, MemoryAlloc},
|
||||
DedicatedTo, ExternalMemoryHandleType, ExternalMemoryHandleTypes, MemoryRequirements,
|
||||
DedicatedTo, ExternalMemoryHandleType, ExternalMemoryHandleTypes, MemoryPropertyFlags,
|
||||
MemoryRequirements,
|
||||
},
|
||||
range_map::RangeMap,
|
||||
swapchain::Swapchain,
|
||||
@ -140,13 +141,14 @@ impl RawImage {
|
||||
let format = format.unwrap(); // Can be None for "external formats" but Vulkano doesn't support that yet
|
||||
let aspects = format.aspects();
|
||||
|
||||
let has_separate_stencil_usage =
|
||||
if stencil_usage.is_empty() || !(aspects.depth && aspects.stencil) {
|
||||
stencil_usage = usage;
|
||||
false
|
||||
} else {
|
||||
stencil_usage == usage
|
||||
};
|
||||
let has_separate_stencil_usage = if stencil_usage.is_empty()
|
||||
|| !aspects.contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
|
||||
{
|
||||
stencil_usage = usage;
|
||||
false
|
||||
} else {
|
||||
stencil_usage == usage
|
||||
};
|
||||
|
||||
// VUID-VkImageCreateInfo-flags-parameter
|
||||
flags.validate_device(device)?;
|
||||
@ -171,7 +173,8 @@ impl RawImage {
|
||||
|| device.enabled_extensions().ext_separate_stencil_usage)
|
||||
{
|
||||
return Err(ImageError::RequirementNotMet {
|
||||
required_for: "`create_info.stencil_usage` is `Some` and `create_info.format` has both a depth and a stencil aspect",
|
||||
required_for: "`create_info.stencil_usage` is `Some` and `create_info.format` \
|
||||
has both a depth and a stencil aspect",
|
||||
requires_one_of: RequiresOneOf {
|
||||
api_version: Some(Version::V1_2),
|
||||
device_extensions: &["ext_separate_stencil_usage"],
|
||||
@ -197,7 +200,10 @@ impl RawImage {
|
||||
));
|
||||
|
||||
// VUID-VkImageCreateInfo-flags-01573
|
||||
assert!(!flags.block_texel_view_compatible || flags.mutable_format);
|
||||
assert!(
|
||||
!flags.intersects(ImageCreateFlags::BLOCK_TEXEL_VIEW_COMPATIBLE)
|
||||
|| flags.intersects(ImageCreateFlags::MUTABLE_FORMAT)
|
||||
);
|
||||
|
||||
// Get format features
|
||||
let format_features = {
|
||||
@ -266,7 +272,7 @@ impl RawImage {
|
||||
return Err(ImageError::MultisampleNot2d);
|
||||
}
|
||||
|
||||
if flags.cube_compatible {
|
||||
if flags.intersects(ImageCreateFlags::CUBE_COMPATIBLE) {
|
||||
return Err(ImageError::MultisampleCubeCompatible);
|
||||
}
|
||||
|
||||
@ -284,10 +290,9 @@ impl RawImage {
|
||||
&& array_layers != 1
|
||||
{
|
||||
return Err(ImageError::RequirementNotMet {
|
||||
required_for:
|
||||
"this device is a portability subset device, `create_info.samples` is not \
|
||||
`SampleCount::Sample1` and `create_info.dimensions.array_layers()` is \
|
||||
greater than `1`",
|
||||
required_for: "this device is a portability subset device, \
|
||||
`create_info.samples` is not `SampleCount::Sample1` and \
|
||||
`create_info.dimensions.array_layers()` is greater than `1`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
features: &["multisample_array_image"],
|
||||
..Default::default()
|
||||
@ -316,7 +321,8 @@ impl RawImage {
|
||||
// VUID-VkImageCreateInfo-format-06413
|
||||
if array_layers > 1 && !device.enabled_features().ycbcr_image_arrays {
|
||||
return Err(ImageError::RequirementNotMet {
|
||||
required_for: "`create_info.format.ycbcr_chroma_sampling()` is `Some` and `create_info.dimensions.array_layers()` is greater than `1`",
|
||||
required_for: "`create_info.format.ycbcr_chroma_sampling()` is `Some` and \
|
||||
`create_info.dimensions.array_layers()` is greater than `1`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
features: &["ycbcr_image_arrays"],
|
||||
..Default::default()
|
||||
@ -346,35 +352,44 @@ impl RawImage {
|
||||
|
||||
let combined_usage = usage | stencil_usage;
|
||||
|
||||
if combined_usage.sampled && !format_features.sampled_image {
|
||||
if combined_usage.intersects(ImageUsage::SAMPLED)
|
||||
&& !format_features.intersects(FormatFeatures::SAMPLED_IMAGE)
|
||||
{
|
||||
return Err(ImageError::FormatUsageNotSupported { usage: "sampled" });
|
||||
}
|
||||
|
||||
if combined_usage.color_attachment && !format_features.color_attachment {
|
||||
if combined_usage.intersects(ImageUsage::COLOR_ATTACHMENT)
|
||||
&& !format_features.intersects(FormatFeatures::COLOR_ATTACHMENT)
|
||||
{
|
||||
return Err(ImageError::FormatUsageNotSupported {
|
||||
usage: "color_attachment",
|
||||
});
|
||||
}
|
||||
|
||||
if combined_usage.depth_stencil_attachment && !format_features.depth_stencil_attachment {
|
||||
if combined_usage.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
|
||||
&& !format_features.intersects(FormatFeatures::DEPTH_STENCIL_ATTACHMENT)
|
||||
{
|
||||
return Err(ImageError::FormatUsageNotSupported {
|
||||
usage: "depth_stencil_attachment",
|
||||
});
|
||||
}
|
||||
|
||||
if combined_usage.input_attachment
|
||||
&& !(format_features.color_attachment || format_features.depth_stencil_attachment)
|
||||
if combined_usage.intersects(ImageUsage::INPUT_ATTACHMENT)
|
||||
&& !format_features.intersects(
|
||||
FormatFeatures::COLOR_ATTACHMENT | FormatFeatures::DEPTH_STENCIL_ATTACHMENT,
|
||||
)
|
||||
{
|
||||
return Err(ImageError::FormatUsageNotSupported {
|
||||
usage: "input_attachment",
|
||||
});
|
||||
}
|
||||
|
||||
if combined_usage.color_attachment
|
||||
|| combined_usage.depth_stencil_attachment
|
||||
|| combined_usage.input_attachment
|
||||
|| combined_usage.transient_attachment
|
||||
{
|
||||
if combined_usage.intersects(
|
||||
ImageUsage::COLOR_ATTACHMENT
|
||||
| ImageUsage::DEPTH_STENCIL_ATTACHMENT
|
||||
| ImageUsage::INPUT_ATTACHMENT
|
||||
| ImageUsage::TRANSIENT_ATTACHMENT,
|
||||
) {
|
||||
// VUID-VkImageCreateInfo-usage-00964
|
||||
// VUID-VkImageCreateInfo-usage-00965
|
||||
// VUID-VkImageCreateInfo-Format-02536
|
||||
@ -392,8 +407,8 @@ impl RawImage {
|
||||
}
|
||||
}
|
||||
|
||||
if combined_usage.storage {
|
||||
if !format_features.storage_image {
|
||||
if combined_usage.intersects(ImageUsage::STORAGE) {
|
||||
if !format_features.intersects(FormatFeatures::STORAGE_IMAGE) {
|
||||
return Err(ImageError::FormatUsageNotSupported { usage: "storage" });
|
||||
}
|
||||
|
||||
@ -403,7 +418,9 @@ impl RawImage {
|
||||
&& samples != SampleCount::Sample1
|
||||
{
|
||||
return Err(ImageError::RequirementNotMet {
|
||||
required_for: "`create_info.usage.storage` or `create_info.stencil_usage.storage` is set and `create_info.samples` is not `SampleCount::Sample1`",
|
||||
required_for: "`create_info.usage` or `create_info.stencil_usage` contains \
|
||||
`ImageUsage::STORAGE`, and `create_info.samples` is not \
|
||||
`SampleCount::Sample1`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
features: &["shader_storage_image_multisample"],
|
||||
..Default::default()
|
||||
@ -414,40 +431,46 @@ impl RawImage {
|
||||
|
||||
// These flags only exist in later versions, ignore them otherwise
|
||||
if device.api_version() >= Version::V1_1 || device.enabled_extensions().khr_maintenance1 {
|
||||
if combined_usage.transfer_src && !format_features.transfer_src {
|
||||
if combined_usage.intersects(ImageUsage::TRANSFER_SRC)
|
||||
&& !format_features.intersects(FormatFeatures::TRANSFER_SRC)
|
||||
{
|
||||
return Err(ImageError::FormatUsageNotSupported {
|
||||
usage: "transfer_src",
|
||||
});
|
||||
}
|
||||
|
||||
if combined_usage.transfer_dst && !format_features.transfer_dst {
|
||||
if combined_usage.intersects(ImageUsage::TRANSFER_DST)
|
||||
&& !format_features.intersects(FormatFeatures::TRANSFER_DST)
|
||||
{
|
||||
return Err(ImageError::FormatUsageNotSupported {
|
||||
usage: "transfer_dst",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if usage.transient_attachment {
|
||||
if usage.intersects(ImageUsage::TRANSIENT_ATTACHMENT) {
|
||||
// VUID-VkImageCreateInfo-usage-00966
|
||||
assert!(
|
||||
usage.color_attachment || usage.depth_stencil_attachment || usage.input_attachment
|
||||
);
|
||||
assert!(usage.intersects(
|
||||
ImageUsage::COLOR_ATTACHMENT
|
||||
| ImageUsage::DEPTH_STENCIL_ATTACHMENT
|
||||
| ImageUsage::INPUT_ATTACHMENT
|
||||
));
|
||||
|
||||
// VUID-VkImageCreateInfo-usage-00963
|
||||
assert!(ImageUsage {
|
||||
transient_attachment: false,
|
||||
color_attachment: false,
|
||||
depth_stencil_attachment: false,
|
||||
input_attachment: false,
|
||||
..usage
|
||||
}
|
||||
.is_empty())
|
||||
assert!((usage
|
||||
- (ImageUsage::TRANSIENT_ATTACHMENT
|
||||
| ImageUsage::COLOR_ATTACHMENT
|
||||
| ImageUsage::DEPTH_STENCIL_ATTACHMENT
|
||||
| ImageUsage::INPUT_ATTACHMENT))
|
||||
.is_empty())
|
||||
}
|
||||
|
||||
if has_separate_stencil_usage {
|
||||
// VUID-VkImageCreateInfo-format-02795
|
||||
// VUID-VkImageCreateInfo-format-02796
|
||||
if usage.depth_stencil_attachment != stencil_usage.depth_stencil_attachment {
|
||||
if usage.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
|
||||
!= stencil_usage.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
|
||||
{
|
||||
return Err(ImageError::StencilUsageMismatch {
|
||||
usage,
|
||||
stencil_usage,
|
||||
@ -456,28 +479,28 @@ impl RawImage {
|
||||
|
||||
// VUID-VkImageCreateInfo-format-02797
|
||||
// VUID-VkImageCreateInfo-format-02798
|
||||
if usage.transient_attachment != stencil_usage.transient_attachment {
|
||||
if usage.intersects(ImageUsage::TRANSIENT_ATTACHMENT)
|
||||
!= stencil_usage.intersects(ImageUsage::TRANSIENT_ATTACHMENT)
|
||||
{
|
||||
return Err(ImageError::StencilUsageMismatch {
|
||||
usage,
|
||||
stencil_usage,
|
||||
});
|
||||
}
|
||||
|
||||
if stencil_usage.transient_attachment {
|
||||
if stencil_usage.intersects(ImageUsage::TRANSIENT_ATTACHMENT) {
|
||||
// VUID-VkImageStencilUsageCreateInfo-stencilUsage-02539
|
||||
assert!(ImageUsage {
|
||||
transient_attachment: false,
|
||||
depth_stencil_attachment: false,
|
||||
input_attachment: false,
|
||||
..stencil_usage
|
||||
}
|
||||
.is_empty())
|
||||
assert!((stencil_usage
|
||||
- (ImageUsage::TRANSIENT_ATTACHMENT
|
||||
| ImageUsage::DEPTH_STENCIL_ATTACHMENT
|
||||
| ImageUsage::INPUT_ATTACHMENT))
|
||||
.is_empty())
|
||||
}
|
||||
}
|
||||
|
||||
/* Check flags requirements */
|
||||
|
||||
if flags.cube_compatible {
|
||||
if flags.intersects(ImageCreateFlags::CUBE_COMPATIBLE) {
|
||||
// VUID-VkImageCreateInfo-flags-00949
|
||||
if image_type != ImageType::Dim2d {
|
||||
return Err(ImageError::CubeCompatibleNot2d);
|
||||
@ -494,7 +517,7 @@ impl RawImage {
|
||||
}
|
||||
}
|
||||
|
||||
if flags.array_2d_compatible {
|
||||
if flags.intersects(ImageCreateFlags::ARRAY_2D_COMPATIBLE) {
|
||||
// VUID-VkImageCreateInfo-flags-00950
|
||||
if image_type != ImageType::Dim3d {
|
||||
return Err(ImageError::Array2dCompatibleNot3d);
|
||||
@ -505,9 +528,8 @@ impl RawImage {
|
||||
&& !device.enabled_features().image_view2_d_on3_d_image
|
||||
{
|
||||
return Err(ImageError::RequirementNotMet {
|
||||
required_for:
|
||||
"this device is a portability subset device, and the `array_2d_compatible`
|
||||
flag is enabled",
|
||||
required_for: "this device is a portability subset device, and \
|
||||
`create_info.flags` contains `ImageCreateFlags::ARRAY_2D_COMPATIBLE`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
features: &["image_view2_d_on3_d_image"],
|
||||
..Default::default()
|
||||
@ -516,21 +538,21 @@ impl RawImage {
|
||||
}
|
||||
}
|
||||
|
||||
if flags.block_texel_view_compatible {
|
||||
if flags.intersects(ImageCreateFlags::BLOCK_TEXEL_VIEW_COMPATIBLE) {
|
||||
// VUID-VkImageCreateInfo-flags-01572
|
||||
if format.compression().is_none() {
|
||||
return Err(ImageError::BlockTexelViewCompatibleNotCompressed);
|
||||
}
|
||||
}
|
||||
|
||||
if flags.disjoint {
|
||||
if flags.intersects(ImageCreateFlags::DISJOINT) {
|
||||
// VUID-VkImageCreateInfo-format-01577
|
||||
if format.planes().len() < 2 {
|
||||
return Err(ImageError::DisjointFormatNotSupported);
|
||||
}
|
||||
|
||||
// VUID-VkImageCreateInfo-imageCreateFormatFeatures-02260
|
||||
if !format_features.disjoint {
|
||||
if !format_features.intersects(FormatFeatures::DISJOINT) {
|
||||
return Err(ImageError::DisjointFormatNotSupported);
|
||||
}
|
||||
}
|
||||
@ -598,7 +620,7 @@ impl RawImage {
|
||||
let limit = device.physical_device().properties().max_image_dimension1_d;
|
||||
extent[0] > limit
|
||||
}
|
||||
ImageType::Dim2d if flags.cube_compatible => {
|
||||
ImageType::Dim2d if flags.intersects(ImageCreateFlags::CUBE_COMPATIBLE) => {
|
||||
let limit = device
|
||||
.physical_device()
|
||||
.properties()
|
||||
@ -641,41 +663,41 @@ impl RawImage {
|
||||
return false;
|
||||
}
|
||||
|
||||
if combined_usage.color_attachment
|
||||
if combined_usage.intersects(ImageUsage::COLOR_ATTACHMENT)
|
||||
&& !device_properties
|
||||
.framebuffer_color_sample_counts
|
||||
.contains_count(samples)
|
||||
.contains_enum(samples)
|
||||
{
|
||||
// TODO: how to handle framebuffer_integer_color_sample_counts limit, which only
|
||||
// exists >= Vulkan 1.2
|
||||
return true;
|
||||
}
|
||||
|
||||
if combined_usage.depth_stencil_attachment {
|
||||
if aspects.depth
|
||||
if combined_usage.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT) {
|
||||
if aspects.intersects(ImageAspects::DEPTH)
|
||||
&& !device_properties
|
||||
.framebuffer_depth_sample_counts
|
||||
.contains_count(samples)
|
||||
.contains_enum(samples)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if aspects.stencil
|
||||
if aspects.intersects(ImageAspects::STENCIL)
|
||||
&& !device_properties
|
||||
.framebuffer_stencil_sample_counts
|
||||
.contains_count(samples)
|
||||
.contains_enum(samples)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if combined_usage.sampled {
|
||||
if combined_usage.intersects(ImageUsage::SAMPLED) {
|
||||
if let Some(numeric_type) = format.type_color() {
|
||||
match numeric_type {
|
||||
NumericType::UINT | NumericType::SINT => {
|
||||
if !device_properties
|
||||
.sampled_image_integer_sample_counts
|
||||
.contains_count(samples)
|
||||
.contains_enum(samples)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -689,35 +711,35 @@ impl RawImage {
|
||||
| NumericType::SRGB => {
|
||||
if !device_properties
|
||||
.sampled_image_color_sample_counts
|
||||
.contains_count(samples)
|
||||
.contains_enum(samples)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if aspects.depth
|
||||
if aspects.intersects(ImageAspects::DEPTH)
|
||||
&& !device_properties
|
||||
.sampled_image_depth_sample_counts
|
||||
.contains_count(samples)
|
||||
.contains_enum(samples)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if aspects.stencil
|
||||
if aspects.intersects(ImageAspects::STENCIL)
|
||||
&& device_properties
|
||||
.sampled_image_stencil_sample_counts
|
||||
.contains_count(samples)
|
||||
.contains_enum(samples)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if combined_usage.storage
|
||||
if combined_usage.intersects(ImageUsage::STORAGE)
|
||||
&& !device_properties
|
||||
.storage_image_sample_counts
|
||||
.contains_count(samples)
|
||||
.contains_enum(samples)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -733,11 +755,7 @@ impl RawImage {
|
||||
&& array_layers == 1
|
||||
// VUID-VkImageCreateInfo-samples-02257 already states that multisampling+linear
|
||||
// is invalid so no need to check for that here.
|
||||
&& ImageUsage {
|
||||
transfer_src: false,
|
||||
transfer_dst: false,
|
||||
..usage
|
||||
}.is_empty())
|
||||
&& (usage - (ImageUsage::TRANSFER_SRC | ImageUsage::TRANSFER_DST)).is_empty())
|
||||
} else {
|
||||
false
|
||||
}
|
||||
@ -756,7 +774,7 @@ impl RawImage {
|
||||
if !external_memory_handle_types.is_empty() {
|
||||
// If external memory handles are used, the properties need to be queried
|
||||
// individually for each handle type.
|
||||
external_memory_handle_types.iter().map(Some).collect()
|
||||
external_memory_handle_types.into_iter().map(Some).collect()
|
||||
} else {
|
||||
smallvec![None]
|
||||
};
|
||||
@ -819,7 +837,7 @@ impl RawImage {
|
||||
}
|
||||
|
||||
// VUID-VkImageCreateInfo-samples-02258
|
||||
if !sample_counts.contains_count(samples) {
|
||||
if !sample_counts.contains_enum(samples) {
|
||||
return Err(ImageError::SampleCountNotSupported {
|
||||
samples,
|
||||
supported: sample_counts,
|
||||
@ -856,13 +874,14 @@ impl RawImage {
|
||||
|
||||
let aspects = format.map_or_else(Default::default, |format| format.aspects());
|
||||
|
||||
let has_separate_stencil_usage =
|
||||
if stencil_usage.is_empty() || !(aspects.depth && aspects.stencil) {
|
||||
stencil_usage = usage;
|
||||
false
|
||||
} else {
|
||||
stencil_usage == usage
|
||||
};
|
||||
let has_separate_stencil_usage = if stencil_usage.is_empty()
|
||||
|| !aspects.contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
|
||||
{
|
||||
stencil_usage = usage;
|
||||
false
|
||||
} else {
|
||||
stencil_usage == usage
|
||||
};
|
||||
|
||||
let (image_type, extent, array_layers) = match dimensions {
|
||||
ImageDimensions::Dim1d {
|
||||
@ -984,7 +1003,9 @@ impl RawImage {
|
||||
|
||||
let aspects = format.map_or_else(Default::default, |format| format.aspects());
|
||||
|
||||
if stencil_usage.is_empty() || !(aspects.depth && aspects.stencil) {
|
||||
if stencil_usage.is_empty()
|
||||
|| !aspects.contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
|
||||
{
|
||||
stencil_usage = usage;
|
||||
}
|
||||
|
||||
@ -1001,7 +1022,7 @@ impl RawImage {
|
||||
}
|
||||
};
|
||||
|
||||
let memory_requirements = if flags.disjoint {
|
||||
let memory_requirements = if flags.intersects(ImageCreateFlags::DISJOINT) {
|
||||
(0..format.unwrap().planes().len())
|
||||
.map(|plane| Self::get_memory_requirements(&device, handle, Some(plane)))
|
||||
.collect()
|
||||
@ -1342,7 +1363,7 @@ impl RawImage {
|
||||
}
|
||||
|
||||
fn validate_bind_memory(&self, allocations: &[MemoryAlloc]) -> Result<(), ImageError> {
|
||||
if self.flags.disjoint {
|
||||
if self.flags.intersects(ImageCreateFlags::DISJOINT) {
|
||||
if allocations.len() != self.format.unwrap().planes().len() {
|
||||
return Err(ImageError::AllocationsWrongNumberOfElements {
|
||||
provided: allocations.len(),
|
||||
@ -1398,7 +1419,10 @@ impl RawImage {
|
||||
}
|
||||
|
||||
// VUID-VkBindImageMemoryInfo-None-01901
|
||||
if memory_type.property_flags.protected {
|
||||
if memory_type
|
||||
.property_flags
|
||||
.intersects(MemoryPropertyFlags::PROTECTED)
|
||||
{
|
||||
return Err(ImageError::MemoryProtectedMismatch {
|
||||
allocations_index,
|
||||
image_protected: false,
|
||||
@ -1410,7 +1434,7 @@ impl RawImage {
|
||||
if !memory.export_handle_types().is_empty()
|
||||
&& !memory
|
||||
.export_handle_types()
|
||||
.intersects(&self.external_memory_handle_types)
|
||||
.intersects(self.external_memory_handle_types)
|
||||
{
|
||||
return Err(ImageError::MemoryExternalHandleTypesDisjoint {
|
||||
allocations_index,
|
||||
@ -1422,7 +1446,7 @@ impl RawImage {
|
||||
if let Some(handle_type) = memory.imported_handle_type() {
|
||||
// VUID-VkBindImageMemoryInfo-memory-02989
|
||||
if !ExternalMemoryHandleTypes::from(handle_type)
|
||||
.intersects(&self.external_memory_handle_types)
|
||||
.intersects(self.external_memory_handle_types)
|
||||
{
|
||||
return Err(ImageError::MemoryImportedHandleTypeNotEnabled {
|
||||
allocations_index,
|
||||
@ -1493,7 +1517,7 @@ impl RawImage {
|
||||
let mut infos_vk: SmallVec<[_; 3]> = SmallVec::with_capacity(3);
|
||||
let mut plane_infos_vk: SmallVec<[_; 3]> = SmallVec::with_capacity(3);
|
||||
|
||||
if self.flags.disjoint {
|
||||
if self.flags.intersects(ImageCreateFlags::DISJOINT) {
|
||||
debug_assert_eq!(allocations.len(), self.format.unwrap().planes().len());
|
||||
|
||||
for (plane, allocation) in allocations.iter().enumerate() {
|
||||
@ -1602,8 +1626,8 @@ impl RawImage {
|
||||
|
||||
/// Returns the features supported by the image's format.
|
||||
#[inline]
|
||||
pub fn format_features(&self) -> &FormatFeatures {
|
||||
&self.format_features
|
||||
pub fn format_features(&self) -> FormatFeatures {
|
||||
self.format_features
|
||||
}
|
||||
|
||||
/// Returns the number of mipmap levels in the image.
|
||||
@ -1632,14 +1656,14 @@ impl RawImage {
|
||||
|
||||
/// Returns the usage the image was created with.
|
||||
#[inline]
|
||||
pub fn usage(&self) -> &ImageUsage {
|
||||
&self.usage
|
||||
pub fn usage(&self) -> ImageUsage {
|
||||
self.usage
|
||||
}
|
||||
|
||||
/// Returns the stencil usage the image was created with.
|
||||
#[inline]
|
||||
pub fn stencil_usage(&self) -> &ImageUsage {
|
||||
&self.stencil_usage
|
||||
pub fn stencil_usage(&self) -> ImageUsage {
|
||||
self.stencil_usage
|
||||
}
|
||||
|
||||
/// Returns the sharing the image was created with.
|
||||
@ -1662,11 +1686,8 @@ impl RawImage {
|
||||
aspects: {
|
||||
let aspects = self.format.unwrap().aspects();
|
||||
|
||||
if aspects.plane0 {
|
||||
ImageAspects {
|
||||
plane0: true,
|
||||
..ImageAspects::empty()
|
||||
}
|
||||
if aspects.intersects(ImageAspects::PLANE_0) {
|
||||
ImageAspects::PLANE_0
|
||||
} else {
|
||||
aspects
|
||||
}
|
||||
@ -1681,12 +1702,8 @@ impl RawImage {
|
||||
#[inline]
|
||||
pub fn subresource_range(&self) -> ImageSubresourceRange {
|
||||
ImageSubresourceRange {
|
||||
aspects: ImageAspects {
|
||||
plane0: false,
|
||||
plane1: false,
|
||||
plane2: false,
|
||||
..self.format.unwrap().aspects()
|
||||
},
|
||||
aspects: self.format.unwrap().aspects()
|
||||
- (ImageAspects::PLANE_0 | ImageAspects::PLANE_1 | ImageAspects::PLANE_2),
|
||||
mip_levels: 0..self.mip_levels,
|
||||
array_layers: 0..self.dimensions.array_layers(),
|
||||
}
|
||||
@ -1754,12 +1771,14 @@ impl RawImage {
|
||||
// VUID-vkGetImageSubresourceLayout-aspectMask-00997
|
||||
// VUID-vkGetImageSubresourceLayout-format-04462
|
||||
// VUID-vkGetImageSubresourceLayout-format-04463
|
||||
if allowed_aspects.depth && allowed_aspects.stencil {
|
||||
if allowed_aspects.contains(ImageAspects::DEPTH | ImageAspects::STENCIL) {
|
||||
return Err(ImageError::DepthStencilFormatsNotSupported);
|
||||
}
|
||||
|
||||
if allowed_aspects.plane0 || allowed_aspects.plane1 || allowed_aspects.plane2 {
|
||||
allowed_aspects.color = false;
|
||||
if allowed_aspects
|
||||
.intersects(ImageAspects::PLANE_0 | ImageAspects::PLANE_1 | ImageAspects::PLANE_2)
|
||||
{
|
||||
allowed_aspects -= ImageAspects::COLOR;
|
||||
}
|
||||
|
||||
// VUID-vkGetImageSubresourceLayout-format-04461
|
||||
@ -1768,7 +1787,7 @@ impl RawImage {
|
||||
// VUID-vkGetImageSubresourceLayout-format-04464
|
||||
// VUID-vkGetImageSubresourceLayout-format-01581
|
||||
// VUID-vkGetImageSubresourceLayout-format-01582
|
||||
if !allowed_aspects.contains(&aspect.into()) {
|
||||
if !allowed_aspects.contains(aspect.into()) {
|
||||
return Err(ImageError::AspectNotAllowed {
|
||||
provided_aspect: aspect,
|
||||
allowed_aspects,
|
||||
@ -1997,7 +2016,7 @@ pub enum ImageMemory {
|
||||
impl Image {
|
||||
fn from_raw(inner: RawImage, memory: ImageMemory) -> Self {
|
||||
let aspects = inner.format.unwrap().aspects();
|
||||
let aspect_list: SmallVec<[ImageAspect; 4]> = aspects.iter().collect();
|
||||
let aspect_list: SmallVec<[ImageAspect; 4]> = aspects.into_iter().collect();
|
||||
let mip_level_size = inner.dimensions.array_layers() as DeviceSize;
|
||||
let aspect_size = mip_level_size * inner.mip_levels as DeviceSize;
|
||||
let range_size = aspect_list.len() as DeviceSize * aspect_size;
|
||||
@ -2088,8 +2107,8 @@ impl Image {
|
||||
|
||||
/// Returns the features supported by the image's format.
|
||||
#[inline]
|
||||
pub fn format_features(&self) -> &FormatFeatures {
|
||||
&self.inner.format_features
|
||||
pub fn format_features(&self) -> FormatFeatures {
|
||||
self.inner.format_features
|
||||
}
|
||||
|
||||
/// Returns the number of mipmap levels in the image.
|
||||
@ -2118,14 +2137,14 @@ impl Image {
|
||||
|
||||
/// Returns the usage the image was created with.
|
||||
#[inline]
|
||||
pub fn usage(&self) -> &ImageUsage {
|
||||
&self.inner.usage
|
||||
pub fn usage(&self) -> ImageUsage {
|
||||
self.inner.usage
|
||||
}
|
||||
|
||||
/// Returns the stencil usage the image was created with.
|
||||
#[inline]
|
||||
pub fn stencil_usage(&self) -> &ImageUsage {
|
||||
&self.inner.stencil_usage
|
||||
pub fn stencil_usage(&self) -> ImageUsage {
|
||||
self.inner.stencil_usage
|
||||
}
|
||||
|
||||
/// Returns the sharing the image was created with.
|
||||
@ -2206,7 +2225,7 @@ impl Image {
|
||||
.format()
|
||||
.unwrap()
|
||||
.aspects()
|
||||
.contains(&subresource_range.aspects));
|
||||
.contains(subresource_range.aspects));
|
||||
assert!(subresource_range.mip_levels.end <= self.inner.mip_levels);
|
||||
assert!(subresource_range.array_layers.end <= self.inner.dimensions.array_layers());
|
||||
|
||||
@ -2608,7 +2627,7 @@ impl SubresourceRangeIterator {
|
||||
|
||||
let mut aspect_nums = subresource_range
|
||||
.aspects
|
||||
.iter()
|
||||
.into_iter()
|
||||
.map(|aspect| image_aspect_list.iter().position(|&a| a == aspect).unwrap())
|
||||
.collect::<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,15 +3439,12 @@ mod tests {
|
||||
#[allow(clippy::erasing_op, clippy::identity_op)]
|
||||
fn subresource_range_iterator() {
|
||||
// A fictitious set of aspects that no real image would actually ever have.
|
||||
let image_aspect_list: SmallVec<[ImageAspect; 4]> = ImageAspects {
|
||||
color: true,
|
||||
depth: true,
|
||||
stencil: true,
|
||||
plane0: true,
|
||||
..ImageAspects::empty()
|
||||
}
|
||||
.iter()
|
||||
.collect();
|
||||
let image_aspect_list: SmallVec<[ImageAspect; 4]> = (ImageAspects::COLOR
|
||||
| ImageAspects::DEPTH
|
||||
| ImageAspects::STENCIL
|
||||
| ImageAspects::PLANE_0)
|
||||
.into_iter()
|
||||
.collect();
|
||||
let image_mip_levels = 6;
|
||||
let image_array_layers = 8;
|
||||
|
||||
@ -3467,13 +3454,10 @@ mod tests {
|
||||
// Whole image
|
||||
let mut iter = SubresourceRangeIterator::new(
|
||||
ImageSubresourceRange {
|
||||
aspects: ImageAspects {
|
||||
color: true,
|
||||
depth: true,
|
||||
stencil: true,
|
||||
plane0: true,
|
||||
..ImageAspects::empty()
|
||||
},
|
||||
aspects: ImageAspects::COLOR
|
||||
| ImageAspects::DEPTH
|
||||
| ImageAspects::STENCIL
|
||||
| ImageAspects::PLANE_0,
|
||||
mip_levels: 0..6,
|
||||
array_layers: 0..8,
|
||||
},
|
||||
@ -3490,13 +3474,7 @@ mod tests {
|
||||
// Only some aspects
|
||||
let mut iter = SubresourceRangeIterator::new(
|
||||
ImageSubresourceRange {
|
||||
aspects: ImageAspects {
|
||||
color: true,
|
||||
depth: true,
|
||||
stencil: false,
|
||||
plane0: true,
|
||||
..ImageAspects::empty()
|
||||
},
|
||||
aspects: ImageAspects::COLOR | ImageAspects::DEPTH | ImageAspects::PLANE_0,
|
||||
mip_levels: 0..6,
|
||||
array_layers: 0..8,
|
||||
},
|
||||
@ -3514,13 +3492,7 @@ mod tests {
|
||||
// Two aspects, and only some of the mip levels
|
||||
let mut iter = SubresourceRangeIterator::new(
|
||||
ImageSubresourceRange {
|
||||
aspects: ImageAspects {
|
||||
color: false,
|
||||
depth: true,
|
||||
stencil: true,
|
||||
plane0: false,
|
||||
..ImageAspects::empty()
|
||||
},
|
||||
aspects: ImageAspects::DEPTH | ImageAspects::STENCIL,
|
||||
mip_levels: 2..4,
|
||||
array_layers: 0..8,
|
||||
},
|
||||
@ -3537,13 +3509,8 @@ mod tests {
|
||||
// One aspect, one mip level, only some of the array layers
|
||||
let mut iter = SubresourceRangeIterator::new(
|
||||
ImageSubresourceRange {
|
||||
aspects: ImageAspects {
|
||||
color: true,
|
||||
depth: false,
|
||||
stencil: false,
|
||||
plane0: false,
|
||||
..ImageAspects::empty()
|
||||
},
|
||||
aspects: ImageAspects::COLOR,
|
||||
|
||||
mip_levels: 0..1,
|
||||
array_layers: 2..4,
|
||||
},
|
||||
@ -3563,13 +3530,7 @@ mod tests {
|
||||
// Two aspects, two mip levels, only some of the array layers
|
||||
let mut iter = SubresourceRangeIterator::new(
|
||||
ImageSubresourceRange {
|
||||
aspects: ImageAspects {
|
||||
color: false,
|
||||
depth: true,
|
||||
stencil: true,
|
||||
plane0: false,
|
||||
..ImageAspects::empty()
|
||||
},
|
||||
aspects: ImageAspects::DEPTH | ImageAspects::STENCIL,
|
||||
mip_levels: 2..4,
|
||||
array_layers: 6..8,
|
||||
},
|
||||
|
@ -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(),
|
||||
}
|
||||
|
@ -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],
|
||||
},
|
||||
*/
|
||||
|
@ -19,7 +19,7 @@ use super::{
|
||||
use crate::{
|
||||
device::{Device, DeviceOwned},
|
||||
format::{ChromaSampling, Format, FormatFeatures},
|
||||
image::{ImageAspects, ImageTiling, ImageType, SampleCount},
|
||||
image::{ImageAspects, ImageCreateFlags, ImageTiling, ImageType, SampleCount},
|
||||
macros::vulkan_enum,
|
||||
sampler::{ycbcr::SamplerYcbcrConversion, ComponentMapping},
|
||||
OomError, RequirementNotMet, RequiresOneOf, Version, VulkanError, VulkanObject,
|
||||
@ -145,32 +145,24 @@ where
|
||||
// VUID-VkImageSubresourceRange-aspectMask-parameter
|
||||
subresource_range.aspects.validate_device(device)?;
|
||||
|
||||
{
|
||||
let ImageAspects {
|
||||
color,
|
||||
depth,
|
||||
stencil,
|
||||
metadata,
|
||||
plane0,
|
||||
plane1,
|
||||
plane2,
|
||||
memory_plane0,
|
||||
memory_plane1,
|
||||
memory_plane2,
|
||||
_ne: _,
|
||||
} = subresource_range.aspects;
|
||||
|
||||
assert!(!(metadata || memory_plane0 || memory_plane1 || memory_plane2));
|
||||
assert!({
|
||||
let num_bits = color as u8
|
||||
+ depth as u8
|
||||
+ stencil as u8
|
||||
+ plane0 as u8
|
||||
+ plane1 as u8
|
||||
+ plane2 as u8;
|
||||
num_bits == 1 || depth && stencil && !(color || plane0 || plane1 || plane2)
|
||||
});
|
||||
}
|
||||
assert!(!subresource_range.aspects.intersects(
|
||||
ImageAspects::METADATA
|
||||
| ImageAspects::MEMORY_PLANE_0
|
||||
| ImageAspects::MEMORY_PLANE_1
|
||||
| ImageAspects::MEMORY_PLANE_2
|
||||
));
|
||||
assert!({
|
||||
subresource_range.aspects.count() == 1
|
||||
|| subresource_range
|
||||
.aspects
|
||||
.contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
|
||||
&& !subresource_range.aspects.intersects(
|
||||
ImageAspects::COLOR
|
||||
| ImageAspects::PLANE_0
|
||||
| ImageAspects::PLANE_1
|
||||
| ImageAspects::PLANE_2,
|
||||
)
|
||||
});
|
||||
|
||||
// Get format features
|
||||
let format_features = unsafe { Self::get_format_features(format, image_inner) };
|
||||
@ -180,7 +172,7 @@ where
|
||||
.format()
|
||||
.unwrap()
|
||||
.aspects()
|
||||
.contains(&subresource_range.aspects)
|
||||
.contains(subresource_range.aspects)
|
||||
{
|
||||
return Err(ImageViewCreationError::ImageAspectsNotCompatible {
|
||||
aspects: subresource_range.aspects,
|
||||
@ -203,7 +195,9 @@ where
|
||||
|
||||
// VUID-VkImageViewCreateInfo-image-01003
|
||||
if (view_type == ImageViewType::Cube || view_type == ImageViewType::CubeArray)
|
||||
&& !image_inner.flags().cube_compatible
|
||||
&& !image_inner
|
||||
.flags()
|
||||
.intersects(ImageCreateFlags::CUBE_COMPATIBLE)
|
||||
{
|
||||
return Err(ImageViewCreationError::ImageNotCubeCompatible);
|
||||
}
|
||||
@ -231,7 +225,10 @@ where
|
||||
&& (view_type == ImageViewType::Dim2d || view_type == ImageViewType::Dim2dArray)
|
||||
{
|
||||
// VUID-VkImageViewCreateInfo-image-01005
|
||||
if !image_inner.flags().array_2d_compatible {
|
||||
if !image_inner
|
||||
.flags()
|
||||
.intersects(ImageCreateFlags::ARRAY_2D_COMPATIBLE)
|
||||
{
|
||||
return Err(ImageViewCreationError::ImageNotArray2dCompatible);
|
||||
}
|
||||
|
||||
@ -299,7 +296,7 @@ where
|
||||
// VUID-VkImageViewCreateInfo-pNext-02662
|
||||
// VUID-VkImageViewCreateInfo-pNext-02663
|
||||
// VUID-VkImageViewCreateInfo-pNext-02664
|
||||
if !default_usage.contains(&usage) {
|
||||
if !default_usage.contains(usage) {
|
||||
return Err(ImageViewCreationError::UsageNotSupportedByImage {
|
||||
usage,
|
||||
supported_usage: default_usage,
|
||||
@ -308,43 +305,54 @@ where
|
||||
}
|
||||
|
||||
// VUID-VkImageViewCreateInfo-image-04441
|
||||
if !(image_inner.usage().sampled
|
||||
|| image_inner.usage().storage
|
||||
|| image_inner.usage().color_attachment
|
||||
|| image_inner.usage().depth_stencil_attachment
|
||||
|| image_inner.usage().input_attachment
|
||||
|| image_inner.usage().transient_attachment)
|
||||
{
|
||||
if !image_inner.usage().intersects(
|
||||
ImageUsage::SAMPLED
|
||||
| ImageUsage::STORAGE
|
||||
| ImageUsage::COLOR_ATTACHMENT
|
||||
| ImageUsage::DEPTH_STENCIL_ATTACHMENT
|
||||
| ImageUsage::INPUT_ATTACHMENT
|
||||
| ImageUsage::TRANSIENT_ATTACHMENT,
|
||||
) {
|
||||
return Err(ImageViewCreationError::ImageMissingUsage);
|
||||
}
|
||||
|
||||
// VUID-VkImageViewCreateInfo-usage-02274
|
||||
if usage.sampled && !format_features.sampled_image {
|
||||
if usage.intersects(ImageUsage::SAMPLED)
|
||||
&& !format_features.intersects(FormatFeatures::SAMPLED_IMAGE)
|
||||
{
|
||||
return Err(ImageViewCreationError::FormatUsageNotSupported { usage: "sampled" });
|
||||
}
|
||||
|
||||
// VUID-VkImageViewCreateInfo-usage-02275
|
||||
if usage.storage && !format_features.storage_image {
|
||||
if usage.intersects(ImageUsage::STORAGE)
|
||||
&& !format_features.intersects(FormatFeatures::STORAGE_IMAGE)
|
||||
{
|
||||
return Err(ImageViewCreationError::FormatUsageNotSupported { usage: "storage" });
|
||||
}
|
||||
|
||||
// VUID-VkImageViewCreateInfo-usage-02276
|
||||
if usage.color_attachment && !format_features.color_attachment {
|
||||
if usage.intersects(ImageUsage::COLOR_ATTACHMENT)
|
||||
&& !format_features.intersects(FormatFeatures::COLOR_ATTACHMENT)
|
||||
{
|
||||
return Err(ImageViewCreationError::FormatUsageNotSupported {
|
||||
usage: "color_attachment",
|
||||
});
|
||||
}
|
||||
|
||||
// VUID-VkImageViewCreateInfo-usage-02277
|
||||
if usage.depth_stencil_attachment && !format_features.depth_stencil_attachment {
|
||||
if usage.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
|
||||
&& !format_features.intersects(FormatFeatures::DEPTH_STENCIL_ATTACHMENT)
|
||||
{
|
||||
return Err(ImageViewCreationError::FormatUsageNotSupported {
|
||||
usage: "depth_stencil_attachment",
|
||||
});
|
||||
}
|
||||
|
||||
// VUID-VkImageViewCreateInfo-usage-02652
|
||||
if usage.input_attachment
|
||||
&& !(format_features.color_attachment || format_features.depth_stencil_attachment)
|
||||
if usage.intersects(ImageUsage::INPUT_ATTACHMENT)
|
||||
&& !format_features.intersects(
|
||||
FormatFeatures::COLOR_ATTACHMENT | FormatFeatures::DEPTH_STENCIL_ATTACHMENT,
|
||||
)
|
||||
{
|
||||
return Err(ImageViewCreationError::FormatUsageNotSupported {
|
||||
usage: "input_attachment",
|
||||
@ -355,9 +363,11 @@ where
|
||||
|
||||
if Some(format) != image_inner.format() {
|
||||
// VUID-VkImageViewCreateInfo-image-01762
|
||||
if !image_inner.flags().mutable_format
|
||||
if !image_inner
|
||||
.flags()
|
||||
.intersects(ImageCreateFlags::MUTABLE_FORMAT)
|
||||
|| !image_inner.format().unwrap().planes().is_empty()
|
||||
&& subresource_range.aspects.color
|
||||
&& subresource_range.aspects.intersects(ImageAspects::COLOR)
|
||||
{
|
||||
return Err(ImageViewCreationError::FormatNotCompatible);
|
||||
}
|
||||
@ -370,10 +380,9 @@ where
|
||||
&& format.components() != image_inner.format().unwrap().components()
|
||||
{
|
||||
return Err(ImageViewCreationError::RequirementNotMet {
|
||||
required_for:
|
||||
"this device is a portability subset device, and the format of the image \
|
||||
view does not have the same components and number of bits per component as \
|
||||
the parent image",
|
||||
required_for: "this device is a portability subset device, and the format of \
|
||||
the image view does not have the same components and number of bits per \
|
||||
component as the parent image",
|
||||
requires_one_of: RequiresOneOf {
|
||||
features: &["image_view_format_reinterpretation"],
|
||||
..Default::default()
|
||||
@ -381,7 +390,10 @@ where
|
||||
});
|
||||
}
|
||||
|
||||
if image_inner.flags().block_texel_view_compatible {
|
||||
if image_inner
|
||||
.flags()
|
||||
.intersects(ImageCreateFlags::BLOCK_TEXEL_VIEW_COMPATIBLE)
|
||||
{
|
||||
// VUID-VkImageViewCreateInfo-image-01583
|
||||
if !(format.compatibility() == image_inner.format().unwrap().compatibility()
|
||||
|| format.block_size() == image_inner.format().unwrap().block_size())
|
||||
@ -411,11 +423,11 @@ where
|
||||
return Err(ImageViewCreationError::FormatNotCompatible);
|
||||
}
|
||||
} else {
|
||||
let plane = if subresource_range.aspects.plane0 {
|
||||
let plane = if subresource_range.aspects.intersects(ImageAspects::PLANE_0) {
|
||||
0
|
||||
} else if subresource_range.aspects.plane1 {
|
||||
} else if subresource_range.aspects.intersects(ImageAspects::PLANE_1) {
|
||||
1
|
||||
} else if subresource_range.aspects.plane2 {
|
||||
} else if subresource_range.aspects.intersects(ImageAspects::PLANE_2) {
|
||||
2
|
||||
} else {
|
||||
unreachable!()
|
||||
@ -660,7 +672,7 @@ where
|
||||
format: image_inner.format(),
|
||||
image_type: image.dimensions().image_type(),
|
||||
tiling: image_inner.tiling(),
|
||||
usage: *image_inner.usage(),
|
||||
usage: image_inner.usage(),
|
||||
image_view_type: Some(view_type),
|
||||
..Default::default()
|
||||
})?;
|
||||
@ -689,19 +701,15 @@ where
|
||||
|
||||
// https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VkImageViewCreateInfo.html#_description
|
||||
fn get_default_usage(aspects: ImageAspects, image: &Image) -> ImageUsage {
|
||||
let has_stencil_aspect = aspects.stencil;
|
||||
let has_non_stencil_aspect = !(ImageAspects {
|
||||
stencil: false,
|
||||
..aspects
|
||||
})
|
||||
.is_empty();
|
||||
let has_stencil_aspect = aspects.intersects(ImageAspects::STENCIL);
|
||||
let has_non_stencil_aspect = !(aspects - ImageAspects::STENCIL).is_empty();
|
||||
|
||||
if has_stencil_aspect && has_non_stencil_aspect {
|
||||
*image.usage() & *image.stencil_usage()
|
||||
image.usage() & image.stencil_usage()
|
||||
} else if has_stencil_aspect {
|
||||
*image.stencil_usage()
|
||||
image.stencil_usage()
|
||||
} else if has_non_stencil_aspect {
|
||||
*image.usage()
|
||||
image.usage()
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
@ -711,7 +719,7 @@ where
|
||||
unsafe fn get_format_features(format: Format, image: &Image) -> FormatFeatures {
|
||||
let device = image.device();
|
||||
|
||||
let format_features = if Some(format) != image.format() {
|
||||
let mut format_features = if Some(format) != image.format() {
|
||||
// Use unchecked, because all validation should have been done before calling.
|
||||
let format_properties = device.physical_device().format_properties_unchecked(format);
|
||||
|
||||
@ -720,28 +728,34 @@ where
|
||||
ImageTiling::Linear => format_properties.linear_tiling_features,
|
||||
}
|
||||
} else {
|
||||
*image.format_features()
|
||||
image.format_features()
|
||||
};
|
||||
|
||||
if device.enabled_extensions().khr_format_feature_flags2 {
|
||||
format_features
|
||||
} else {
|
||||
let is_without_format = format.shader_storage_image_without_format();
|
||||
if !device.enabled_extensions().khr_format_feature_flags2 {
|
||||
if format.type_color().is_none()
|
||||
&& format_features.intersects(FormatFeatures::SAMPLED_IMAGE)
|
||||
{
|
||||
format_features |= FormatFeatures::SAMPLED_IMAGE_DEPTH_COMPARISON;
|
||||
}
|
||||
|
||||
FormatFeatures {
|
||||
sampled_image_depth_comparison: format.type_color().is_none()
|
||||
&& format_features.sampled_image,
|
||||
storage_read_without_format: is_without_format
|
||||
&& device
|
||||
.enabled_features()
|
||||
.shader_storage_image_read_without_format,
|
||||
storage_write_without_format: is_without_format
|
||||
&& device
|
||||
.enabled_features()
|
||||
.shader_storage_image_write_without_format,
|
||||
..format_features
|
||||
if format.shader_storage_image_without_format() {
|
||||
if device
|
||||
.enabled_features()
|
||||
.shader_storage_image_read_without_format
|
||||
{
|
||||
format_features |= FormatFeatures::STORAGE_READ_WITHOUT_FORMAT;
|
||||
}
|
||||
|
||||
if device
|
||||
.enabled_features()
|
||||
.shader_storage_image_write_without_format
|
||||
{
|
||||
format_features |= FormatFeatures::STORAGE_WRITE_WITHOUT_FORMAT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
format_features
|
||||
}
|
||||
|
||||
/// Returns the wrapped image that this image view was created from.
|
||||
@ -1146,9 +1160,38 @@ impl From<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]
|
||||
|
@ -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(|_| {}))
|
||||
},
|
||||
)
|
||||
|
@ -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()
|
||||
|
@ -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,
|
||||
|
@ -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,41 +428,52 @@ macro_rules! vulkan_bitflags {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<$ty> for ash::vk::$ty_ffi {
|
||||
#[inline]
|
||||
fn from(#[allow(unused_variables)] val: $ty) -> Self {
|
||||
#[allow(unused_mut)]
|
||||
let mut result = ash::vk::$ty_ffi::empty();
|
||||
$(
|
||||
if val.$flag_name { result |= ash::vk::$ty_ffi::$flag_name_ffi }
|
||||
)*
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
impl From<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())
|
||||
}
|
||||
}
|
||||
|
||||
@ -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};
|
||||
|
@ -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
|
||||
|
@ -18,7 +18,7 @@ use super::{array_vec::ArrayVec, AllocationCreateInfo, AllocationCreationError};
|
||||
use crate::{
|
||||
device::{Device, DeviceOwned},
|
||||
image::ImageTiling,
|
||||
memory::DeviceMemory,
|
||||
memory::{DeviceMemory, MemoryPropertyFlags},
|
||||
DeviceSize, OomError, VulkanError, VulkanObject,
|
||||
};
|
||||
use crossbeam_queue::ArrayQueue;
|
||||
@ -102,7 +102,7 @@ impl MemoryAlloc {
|
||||
[memory_type_index as usize]
|
||||
.property_flags;
|
||||
|
||||
let mapped_ptr = if property_flags.host_visible {
|
||||
let mapped_ptr = if property_flags.intersects(MemoryPropertyFlags::HOST_VISIBLE) {
|
||||
let fns = device.fns();
|
||||
let mut output = MaybeUninit::uninit();
|
||||
// This is always valid because we are mapping the whole range.
|
||||
@ -124,9 +124,10 @@ impl MemoryAlloc {
|
||||
None
|
||||
};
|
||||
|
||||
let atom_size = (property_flags.host_visible && !property_flags.host_coherent)
|
||||
.then_some(physical_device.properties().non_coherent_atom_size)
|
||||
.and_then(NonZeroU64::new);
|
||||
let atom_size = (property_flags.intersects(MemoryPropertyFlags::HOST_VISIBLE)
|
||||
&& !property_flags.intersects(MemoryPropertyFlags::HOST_COHERENT))
|
||||
.then_some(physical_device.properties().non_coherent_atom_size)
|
||||
.and_then(NonZeroU64::new);
|
||||
|
||||
Ok(MemoryAlloc {
|
||||
offset: 0,
|
||||
@ -225,7 +226,7 @@ impl MemoryAlloc {
|
||||
/// - Panics if `range.end` exceeds `self.size`.
|
||||
/// - Panics if `range.start` or `range.end` are not a multiple of the `non_coherent_atom_size`.
|
||||
///
|
||||
/// [host-coherent]: super::MemoryPropertyFlags::host_coherent
|
||||
/// [host-coherent]: crate::memory::MemoryPropertyFlags::HOST_COHERENT
|
||||
/// [`non_coherent_atom_size`]: crate::device::Properties::non_coherent_atom_size
|
||||
#[inline]
|
||||
pub unsafe fn invalidate_range(&self, range: Range<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;
|
||||
///
|
||||
|
@ -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]
|
||||
|
@ -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],
|
||||
},
|
||||
|
@ -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,
|
||||
)
|
||||
|
@ -34,7 +34,8 @@ use super::{
|
||||
use crate::{
|
||||
descriptor_set::layout::{DescriptorSetLayout, DescriptorSetLayoutCreateInfo},
|
||||
device::{Device, DeviceOwned},
|
||||
format::NumericType,
|
||||
format::{FormatFeatures, NumericType},
|
||||
image::ImageAspects,
|
||||
pipeline::{
|
||||
cache::PipelineCache,
|
||||
graphics::{
|
||||
@ -484,7 +485,8 @@ where
|
||||
// VUID-VkGraphicsPipelineCreateInfo-multiview-06577
|
||||
if view_mask != 0 && !device.enabled_features().multiview {
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for: "`render_pass` is `PipelineRenderPassType::BeginRendering` where `view_mask` is not `0`",
|
||||
required_for: "`render_pass` is `PipelineRenderPassType::BeginRendering` \
|
||||
where `view_mask` is not `0`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
features: &["multiview"],
|
||||
..Default::default()
|
||||
@ -519,7 +521,7 @@ where
|
||||
// Use unchecked, because all validation has been done above.
|
||||
if !unsafe { physical_device.format_properties_unchecked(format) }
|
||||
.potential_format_features()
|
||||
.color_attachment
|
||||
.intersects(FormatFeatures::COLOR_ATTACHMENT)
|
||||
{
|
||||
return Err(
|
||||
GraphicsPipelineCreationError::ColorAttachmentFormatUsageNotSupported {
|
||||
@ -537,7 +539,7 @@ where
|
||||
// Use unchecked, because all validation has been done above.
|
||||
if !unsafe { physical_device.format_properties_unchecked(format) }
|
||||
.potential_format_features()
|
||||
.depth_stencil_attachment
|
||||
.intersects(FormatFeatures::DEPTH_STENCIL_ATTACHMENT)
|
||||
{
|
||||
return Err(
|
||||
GraphicsPipelineCreationError::DepthAttachmentFormatUsageNotSupported,
|
||||
@ -545,7 +547,7 @@ where
|
||||
}
|
||||
|
||||
// VUID-VkGraphicsPipelineCreateInfo-renderPass-06587
|
||||
if !format.aspects().depth {
|
||||
if !format.aspects().intersects(ImageAspects::DEPTH) {
|
||||
return Err(
|
||||
GraphicsPipelineCreationError::DepthAttachmentFormatUsageNotSupported,
|
||||
);
|
||||
@ -560,7 +562,7 @@ where
|
||||
// Use unchecked, because all validation has been done above.
|
||||
if !unsafe { physical_device.format_properties_unchecked(format) }
|
||||
.potential_format_features()
|
||||
.depth_stencil_attachment
|
||||
.intersects(FormatFeatures::DEPTH_STENCIL_ATTACHMENT)
|
||||
{
|
||||
return Err(
|
||||
GraphicsPipelineCreationError::StencilAttachmentFormatUsageNotSupported,
|
||||
@ -568,7 +570,7 @@ where
|
||||
}
|
||||
|
||||
// VUID-VkGraphicsPipelineCreateInfo-renderPass-06588
|
||||
if !format.aspects().stencil {
|
||||
if !format.aspects().intersects(ImageAspects::STENCIL) {
|
||||
return Err(
|
||||
GraphicsPipelineCreationError::StencilAttachmentFormatUsageNotSupported,
|
||||
);
|
||||
@ -663,7 +665,9 @@ where
|
||||
.vertex_attribute_instance_rate_divisor
|
||||
{
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for: "`vertex_input_state.bindings` has an element where `input_rate` is `VertexInputRate::Instance`, where `divisor` is not `1`",
|
||||
required_for: "`vertex_input_state.bindings` has an element \
|
||||
where `input_rate` is `VertexInputRate::Instance`, where \
|
||||
`divisor` is not `1`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
features: &["vertex_attribute_instance_rate_divisor"],
|
||||
..Default::default()
|
||||
@ -678,7 +682,9 @@ where
|
||||
.vertex_attribute_instance_rate_zero_divisor
|
||||
{
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for: "`vertex_input_state.bindings` has an element where `input_rate` is `VertexInputRate::Instance`, where `divisor` is `0`",
|
||||
required_for: "`vertex_input_state.bindings` has an element \
|
||||
where `input_rate` is `VertexInputRate::Instance`, where \
|
||||
`divisor` is `0`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
features: &["vertex_attribute_instance_rate_zero_divisor"],
|
||||
..Default::default()
|
||||
@ -754,7 +760,7 @@ where
|
||||
};
|
||||
|
||||
// VUID-VkVertexInputAttributeDescription-format-00623
|
||||
if !format_features.vertex_buffer {
|
||||
if !format_features.intersects(FormatFeatures::VERTEX_BUFFER) {
|
||||
return Err(
|
||||
GraphicsPipelineCreationError::VertexInputAttributeUnsupportedFormat {
|
||||
location,
|
||||
@ -805,9 +811,8 @@ where
|
||||
&& !device.enabled_features().triangle_fans
|
||||
{
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for:
|
||||
"this device is a portability subset device, and \
|
||||
`input_assembly_state.topology` is \
|
||||
required_for: "this device is a portability subset \
|
||||
device, and `input_assembly_state.topology` is \
|
||||
`StateMode::Fixed(PrimitiveTopology::TriangleFan)`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
features: &["triangle_fans"],
|
||||
@ -823,7 +828,8 @@ where
|
||||
// VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00429
|
||||
if !device.enabled_features().geometry_shader {
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for: "`input_assembly_state.topology` is `StateMode::Fixed(PrimitiveTopology::*WithAdjacency)`",
|
||||
required_for: "`input_assembly_state.topology` is \
|
||||
`StateMode::Fixed(PrimitiveTopology::*WithAdjacency)`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
features: &["geometry_shader"],
|
||||
..Default::default()
|
||||
@ -835,7 +841,8 @@ where
|
||||
// VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00430
|
||||
if !device.enabled_features().tessellation_shader {
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for: "`input_assembly_state.topology` is `StateMode::Fixed(PrimitiveTopology::PatchList)`",
|
||||
required_for: "`input_assembly_state.topology` is \
|
||||
`StateMode::Fixed(PrimitiveTopology::PatchList)`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
features: &["tessellation_shader"],
|
||||
..Default::default()
|
||||
@ -858,8 +865,8 @@ where
|
||||
|| device.enabled_features().extended_dynamic_state)
|
||||
{
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for:
|
||||
"`input_assembly_state.topology` is `PartialStateMode::Dynamic`",
|
||||
required_for: "`input_assembly_state.topology` is \
|
||||
`PartialStateMode::Dynamic`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
api_version: Some(Version::V1_3),
|
||||
features: &["extended_dynamic_state"],
|
||||
@ -884,7 +891,10 @@ where
|
||||
// VUID-VkPipelineInputAssemblyStateCreateInfo-topology-06252
|
||||
if !device.enabled_features().primitive_topology_list_restart {
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for: "`input_assembly_state.primitive_restart_enable` is `StateMode::Fixed(true)` and `input_assembly_state.topology` is `StateMode::Fixed(PrimitiveTopology::*List)`",
|
||||
required_for: "`input_assembly_state.primitive_restart_enable` \
|
||||
is `StateMode::Fixed(true)` and \
|
||||
`input_assembly_state.topology` is \
|
||||
`StateMode::Fixed(PrimitiveTopology::*List)`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
features: &["primitive_topology_list_restart"],
|
||||
..Default::default()
|
||||
@ -899,7 +909,10 @@ where
|
||||
.primitive_topology_patch_list_restart
|
||||
{
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for: "`input_assembly_state.primitive_restart_enable` is `StateMode::Fixed(true)` and `input_assembly_state.topology` is `StateMode::Fixed(PrimitiveTopology::PatchList)`",
|
||||
required_for: "`input_assembly_state.primitive_restart_enable` \
|
||||
is `StateMode::Fixed(true)` and \
|
||||
`input_assembly_state.topology` is \
|
||||
`StateMode::Fixed(PrimitiveTopology::PatchList)`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
features: &["primitive_topology_patch_list_restart"],
|
||||
..Default::default()
|
||||
@ -917,7 +930,8 @@ where
|
||||
|| device.enabled_features().extended_dynamic_state2)
|
||||
{
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for: "`input_assembly_state.primitive_restart_enable` is `StateMode::Dynamic`",
|
||||
required_for: "`input_assembly_state.primitive_restart_enable` is \
|
||||
`StateMode::Dynamic`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
api_version: Some(Version::V1_3),
|
||||
features: &["extended_dynamic_state2"],
|
||||
@ -1089,7 +1103,8 @@ where
|
||||
// VUID-VkGraphicsPipelineCreateInfo-renderPass-06057
|
||||
if view_mask != 0 {
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for: "`tessellation_shaders` are provided and `render_pass` has a subpass where `view_mask` is not `0`",
|
||||
required_for: "`tessellation_shaders` are provided and `render_pass` \
|
||||
has a subpass where `view_mask` is not `0`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
features: &["multiview_tessellation_shader"],
|
||||
..Default::default()
|
||||
@ -1158,7 +1173,8 @@ where
|
||||
// VUID-VkGraphicsPipelineCreateInfo-renderPass-06058
|
||||
if view_mask != 0 {
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for: "`geometry_shader` is provided and `render_pass` has a subpass where `view_mask` is not `0`",
|
||||
required_for: "`geometry_shader` is provided and `render_pass` has a \
|
||||
subpass where `view_mask` is not `0`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
features: &["multiview_geometry_shader"],
|
||||
..Default::default()
|
||||
@ -1209,7 +1225,8 @@ where
|
||||
|| device.enabled_features().extended_dynamic_state2)
|
||||
{
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for: "`rasterization_state.rasterizer_discard_enable` is `StateMode::Dynamic`",
|
||||
required_for: "`rasterization_state.rasterizer_discard_enable` is \
|
||||
`StateMode::Dynamic`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
api_version: Some(Version::V1_3),
|
||||
features: &["extended_dynamic_state"],
|
||||
@ -1244,8 +1261,8 @@ where
|
||||
&& !device.enabled_features().fill_mode_non_solid
|
||||
{
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for:
|
||||
"`rasterization_state.polygon_mode` is not `PolygonMode::Fill`",
|
||||
required_for: "`rasterization_state.polygon_mode` is not \
|
||||
`PolygonMode::Fill`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
features: &["fill_mode_non_solid"],
|
||||
..Default::default()
|
||||
@ -1264,8 +1281,8 @@ where
|
||||
|| device.enabled_features().extended_dynamic_state)
|
||||
{
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for:
|
||||
"`rasterization_state.cull_mode` is `StateMode::Dynamic`",
|
||||
required_for: "`rasterization_state.cull_mode` is \
|
||||
`StateMode::Dynamic`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
api_version: Some(Version::V1_3),
|
||||
features: &["extended_dynamic_state"],
|
||||
@ -1287,8 +1304,8 @@ where
|
||||
|| device.enabled_features().extended_dynamic_state)
|
||||
{
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for:
|
||||
"`rasterization_state.front_face` is `StateMode::Dynamic`",
|
||||
required_for: "`rasterization_state.front_face` is \
|
||||
`StateMode::Dynamic`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
api_version: Some(Version::V1_3),
|
||||
features: &["extended_dynamic_state"],
|
||||
@ -1311,7 +1328,9 @@ where
|
||||
|| device.enabled_features().extended_dynamic_state2)
|
||||
{
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for: "`rasterization_state.depth_bias` is `Some(depth_bias_state)`, where `depth_bias_state.enable_dynamic` is set",
|
||||
required_for: "`rasterization_state.depth_bias` is \
|
||||
`Some(depth_bias_state)`, where `depth_bias_state.enable_dynamic` \
|
||||
is set",
|
||||
requires_one_of: RequiresOneOf {
|
||||
api_version: Some(Version::V1_3),
|
||||
features: &["extended_dynamic_state2"],
|
||||
@ -1325,7 +1344,9 @@ where
|
||||
&& !device.enabled_features().depth_bias_clamp
|
||||
{
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for: "`rasterization_state.depth_bias` is `Some(depth_bias_state)`, where `depth_bias_state.bias` is `StateMode::Fixed(bias)`, where `bias.clamp` is not `0.0`",
|
||||
required_for: "`rasterization_state.depth_bias` is \
|
||||
`Some(depth_bias_state)`, where `depth_bias_state.bias` is \
|
||||
`StateMode::Fixed(bias)`, where `bias.clamp` is not `0.0`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
features: &["depth_bias_clamp"],
|
||||
..Default::default()
|
||||
@ -1339,7 +1360,8 @@ where
|
||||
&& !device.enabled_features().wide_lines
|
||||
{
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for: "`rasterization_state.line_width` is `StateMode::Fixed(line_width)`, where `line_width` is not `1.0`",
|
||||
required_for: "`rasterization_state.line_width` is \
|
||||
`StateMode::Fixed(line_width)`, where `line_width` is not `1.0`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
features: &["wide_lines"],
|
||||
..Default::default()
|
||||
@ -1357,7 +1379,8 @@ where
|
||||
// VUID-VkPipelineRasterizationLineStateCreateInfoEXT-lineRasterizationMode-02768
|
||||
if !device.enabled_features().rectangular_lines {
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for: "`rasterization_state.line_rasterization_mode` is `LineRasterizationMode::Rectangular`",
|
||||
required_for: "`rasterization_state.line_rasterization_mode` \
|
||||
is `LineRasterizationMode::Rectangular`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
features: &["rectangular_lines"],
|
||||
..Default::default()
|
||||
@ -1369,7 +1392,8 @@ where
|
||||
// VUID-VkPipelineRasterizationLineStateCreateInfoEXT-lineRasterizationMode-02769
|
||||
if !device.enabled_features().bresenham_lines {
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for: "`rasterization_state.line_rasterization_mode` is `LineRasterizationMode::Bresenham`",
|
||||
required_for: "`rasterization_state.line_rasterization_mode` \
|
||||
is `LineRasterizationMode::Bresenham`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
features: &["bresenham_lines"],
|
||||
..Default::default()
|
||||
@ -1381,7 +1405,8 @@ where
|
||||
// VUID-VkPipelineRasterizationLineStateCreateInfoEXT-lineRasterizationMode-02770
|
||||
if !device.enabled_features().smooth_lines {
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for: "`rasterization_state.line_rasterization_mode` is `LineRasterizationMode::RectangularSmooth`",
|
||||
required_for: "`rasterization_state.line_rasterization_mode` \
|
||||
is `LineRasterizationMode::RectangularSmooth`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
features: &["smooth_lines"],
|
||||
..Default::default()
|
||||
@ -1397,7 +1422,10 @@ where
|
||||
// VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02774
|
||||
if !device.enabled_features().stippled_rectangular_lines {
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for: "`rasterization_state.line_stipple` is `Some` and `rasterization_state.line_rasterization_mode` is `LineRasterizationMode::Default`",
|
||||
required_for: "`rasterization_state.line_stipple` is \
|
||||
`Some` and \
|
||||
`rasterization_state.line_rasterization_mode` \
|
||||
is `LineRasterizationMode::Default`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
features: &["stippled_rectangular_lines"],
|
||||
..Default::default()
|
||||
@ -1416,7 +1444,10 @@ where
|
||||
// VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02771
|
||||
if !device.enabled_features().stippled_rectangular_lines {
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for: "`rasterization_state.line_stipple` is `Some` and `rasterization_state.line_rasterization_mode` is `LineRasterizationMode::Rectangular`",
|
||||
required_for: "`rasterization_state.line_stipple` is \
|
||||
`Some` and \
|
||||
`rasterization_state.line_rasterization_mode` \
|
||||
is `LineRasterizationMode::Rectangular`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
features: &["stippled_rectangular_lines"],
|
||||
..Default::default()
|
||||
@ -1428,7 +1459,10 @@ where
|
||||
// VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02772
|
||||
if !device.enabled_features().stippled_bresenham_lines {
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for: "`rasterization_state.line_stipple` is `Some` and `rasterization_state.line_rasterization_mode` is `LineRasterizationMode::Bresenham`",
|
||||
required_for: "`rasterization_state.line_stipple` is \
|
||||
`Some` and \
|
||||
`rasterization_state.line_rasterization_mode` \
|
||||
is `LineRasterizationMode::Bresenham`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
features: &["stippled_bresenham_lines"],
|
||||
..Default::default()
|
||||
@ -1440,7 +1474,10 @@ where
|
||||
// VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02773
|
||||
if !device.enabled_features().stippled_smooth_lines {
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for: "`rasterization_state.line_stipple` is `Some` and `rasterization_state.line_rasterization_mode` is `LineRasterizationMode::RectangularSmooth`",
|
||||
required_for: "`rasterization_state.line_stipple` is \
|
||||
`Some` and \
|
||||
`rasterization_state.line_rasterization_mode` \
|
||||
is `LineRasterizationMode::RectangularSmooth`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
features: &["stippled_smooth_lines"],
|
||||
..Default::default()
|
||||
@ -1459,7 +1496,8 @@ where
|
||||
} else {
|
||||
if line_rasterization_mode != LineRasterizationMode::Default {
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for: "`rasterization_state.line_rasterization_mode` is not `LineRasterizationMode::Default`",
|
||||
required_for: "`rasterization_state.line_rasterization_mode` is not \
|
||||
`LineRasterizationMode::Default`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
device_extensions: &["ext_line_rasterization"],
|
||||
..Default::default()
|
||||
@ -1509,7 +1547,8 @@ where
|
||||
|
||||
if error {
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for: "`discard_rectangle_state.rectangles` is not `PartialStateMode::Fixed(vec![])`",
|
||||
required_for: "`discard_rectangle_state.rectangles` is not \
|
||||
`PartialStateMode::Fixed(vec![])`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
device_extensions: &["ext_discard_rectangles"],
|
||||
..Default::default()
|
||||
@ -1559,8 +1598,8 @@ where
|
||||
.extended_dynamic_state2_patch_control_points
|
||||
{
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for:
|
||||
"`tessellation_state.patch_control_points` is `StateMode::Dynamic`",
|
||||
required_for: "`tessellation_state.patch_control_points` is \
|
||||
`StateMode::Dynamic`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
features: &["extended_dynamic_state2_patch_control_points"],
|
||||
..Default::default()
|
||||
@ -1637,7 +1676,9 @@ where
|
||||
|| device.enabled_features().extended_dynamic_state)
|
||||
{
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for: "`viewport_state` is `ViewportState::FixedViewport`, where `scissor_count_dynamic` is set",
|
||||
required_for: "`viewport_state` is \
|
||||
`ViewportState::FixedViewport`, where `scissor_count_dynamic` \
|
||||
is set",
|
||||
requires_one_of: RequiresOneOf {
|
||||
api_version: Some(Version::V1_3),
|
||||
features: &["extended_dynamic_state"],
|
||||
@ -1669,7 +1710,9 @@ where
|
||||
|| device.enabled_features().extended_dynamic_state)
|
||||
{
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for: "`viewport_state` is `ViewportState::FixedScissor`, where `viewport_count_dynamic` is set",
|
||||
required_for: "`viewport_state` is \
|
||||
`ViewportState::FixedScissor`, where `viewport_count_dynamic` \
|
||||
is set",
|
||||
requires_one_of: RequiresOneOf {
|
||||
api_version: Some(Version::V1_3),
|
||||
features: &["extended_dynamic_state"],
|
||||
@ -1707,7 +1750,9 @@ where
|
||||
|| device.enabled_features().extended_dynamic_state)
|
||||
{
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for: "`viewport_state` is `ViewportState::Dynamic`, where `viewport_count_dynamic` is set",
|
||||
required_for: "`viewport_state` is \
|
||||
`ViewportState::Dynamic`, where `viewport_count_dynamic` \
|
||||
is set",
|
||||
requires_one_of: RequiresOneOf {
|
||||
api_version: Some(Version::V1_3),
|
||||
features: &["extended_dynamic_state"],
|
||||
@ -1728,7 +1773,9 @@ where
|
||||
|| device.enabled_features().extended_dynamic_state)
|
||||
{
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for: "`viewport_state` is `ViewportState::Dynamic`, where `scissor_count_dynamic` is set",
|
||||
required_for: "`viewport_state` is \
|
||||
`ViewportState::Dynamic`, where `scissor_count_dynamic` \
|
||||
is set",
|
||||
requires_one_of: RequiresOneOf {
|
||||
api_version: Some(Version::V1_3),
|
||||
features: &["extended_dynamic_state"],
|
||||
@ -1756,7 +1803,8 @@ where
|
||||
// VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217
|
||||
if viewport_scissor_count > 1 && !device.enabled_features().multi_viewport {
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for: "`viewport_state` has a fixed viewport/scissor count that is greater than `1`",
|
||||
required_for: "`viewport_state` has a fixed viewport/scissor count that is \
|
||||
greater than `1`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
features: &["multi_viewport"],
|
||||
..Default::default()
|
||||
@ -1867,8 +1915,8 @@ where
|
||||
|| device.enabled_features().extended_dynamic_state)
|
||||
{
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for:
|
||||
"`depth_stencil_state.depth` is `Some(depth_state)`, where `depth_state.enable_dynamic` is set",
|
||||
required_for: "`depth_stencil_state.depth` is `Some(depth_state)`, where \
|
||||
`depth_state.enable_dynamic` is set",
|
||||
requires_one_of: RequiresOneOf {
|
||||
api_version: Some(Version::V1_3),
|
||||
features: &["extended_dynamic_state"],
|
||||
@ -1897,7 +1945,9 @@ where
|
||||
|| device.enabled_features().extended_dynamic_state)
|
||||
{
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for: "`depth_stencil_state.depth` is `Some(depth_state)`, where `depth_state.write_enable` is `StateMode::Dynamic`",
|
||||
required_for: "`depth_stencil_state.depth` is \
|
||||
`Some(depth_state)`, where `depth_state.write_enable` is \
|
||||
`StateMode::Dynamic`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
api_version: Some(Version::V1_3),
|
||||
features: &["extended_dynamic_state"],
|
||||
@ -1919,7 +1969,9 @@ where
|
||||
|| device.enabled_features().extended_dynamic_state)
|
||||
{
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for: "`depth_stencil_state.depth` is `Some(depth_state)`, where `depth_state.compare_op` is `StateMode::Dynamic`",
|
||||
required_for: "`depth_stencil_state.depth` is \
|
||||
`Some(depth_state)`, where `depth_state.compare_op` is \
|
||||
`StateMode::Dynamic`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
api_version: Some(Version::V1_3),
|
||||
features: &["extended_dynamic_state"],
|
||||
@ -1954,7 +2006,9 @@ where
|
||||
|| device.enabled_features().extended_dynamic_state)
|
||||
{
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for: "`depth_stencil_state.depth_bounds` is `Some(depth_bounds_state)`, where `depth_bounds_state.enable_dynamic` is set",
|
||||
required_for: "`depth_stencil_state.depth_bounds` is \
|
||||
`Some(depth_bounds_state)`, where `depth_bounds_state.enable_dynamic` \
|
||||
is set",
|
||||
requires_one_of: RequiresOneOf {
|
||||
api_version: Some(Version::V1_3),
|
||||
features: &["extended_dynamic_state"],
|
||||
@ -1970,7 +2024,9 @@ where
|
||||
&& !(0.0..1.0).contains(bounds.end())
|
||||
{
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for: "`depth_stencil_state.depth_bounds` is `Some(depth_bounds_state)`, where `depth_bounds_state.bounds` is not between `0.0` and `1.0` inclusive",
|
||||
required_for: "`depth_stencil_state.depth_bounds` is \
|
||||
`Some(depth_bounds_state)`, where `depth_bounds_state.bounds` is \
|
||||
not between `0.0` and `1.0` inclusive",
|
||||
requires_one_of: RequiresOneOf {
|
||||
device_extensions: &["ext_depth_range_unrestricted"],
|
||||
..Default::default()
|
||||
@ -2004,8 +2060,8 @@ where
|
||||
|| device.enabled_features().extended_dynamic_state)
|
||||
{
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for:
|
||||
"`depth_stencil_state.stencil` is `Some(stencil_state)`, where `stencil_state.enable_dynamic` is set",
|
||||
required_for: "`depth_stencil_state.stencil` is `Some(stencil_state)`, \
|
||||
where `stencil_state.enable_dynamic` is set",
|
||||
requires_one_of: RequiresOneOf {
|
||||
api_version: Some(Version::V1_3),
|
||||
features: &["extended_dynamic_state"],
|
||||
@ -2043,7 +2099,9 @@ where
|
||||
|| device.enabled_features().extended_dynamic_state)
|
||||
{
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for: "`depth_stencil_state.stencil` is `Some(stencil_state)`, where `stencil_state.front.ops` and `stencil_state.back.ops` are `StateMode::Dynamic`",
|
||||
required_for: "`depth_stencil_state.stencil` is \
|
||||
`Some(stencil_state)`, where `stencil_state.front.ops` and \
|
||||
`stencil_state.back.ops` are `StateMode::Dynamic`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
api_version: Some(Version::V1_3),
|
||||
features: &["extended_dynamic_state"],
|
||||
@ -2209,8 +2267,8 @@ where
|
||||
// VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04869
|
||||
if !device.enabled_features().extended_dynamic_state2_logic_op {
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for:
|
||||
"`color_blend_state.logic_op` is `Some(StateMode::Dynamic)`",
|
||||
required_for: "`color_blend_state.logic_op` is \
|
||||
`Some(StateMode::Dynamic)`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
features: &["extended_dynamic_state2_logic_op"],
|
||||
..Default::default()
|
||||
@ -2247,7 +2305,8 @@ where
|
||||
// VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605
|
||||
if !iter.all(|state| state == first) {
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for: "`color_blend_state.attachments` has elements where `blend` and `color_write_mask` do not match the other elements",
|
||||
required_for: "`color_blend_state.attachments` has elements where \
|
||||
`blend` and `color_write_mask` do not match the other elements",
|
||||
requires_one_of: RequiresOneOf {
|
||||
features: &["independent_blend"],
|
||||
..Default::default()
|
||||
@ -2312,9 +2371,9 @@ where
|
||||
{
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for: "`color_blend_state.attachments` has an element where \
|
||||
`blend` is `Some(blend)`, where `blend.color_source`, \
|
||||
`blend.color_destination`, `blend.alpha_source` or \
|
||||
`blend.alpha_destination` is `BlendFactor::Src1*`",
|
||||
`blend` is `Some(blend)`, where `blend.color_source`, \
|
||||
`blend.color_destination`, `blend.alpha_source` or \
|
||||
`blend.alpha_destination` is `BlendFactor::Src1*`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
features: &["dual_src_blend"],
|
||||
..Default::default()
|
||||
@ -2344,7 +2403,7 @@ where
|
||||
physical_device
|
||||
.format_properties_unchecked(format)
|
||||
.potential_format_features()
|
||||
.color_attachment_blend
|
||||
.intersects(FormatFeatures::COLOR_ATTACHMENT_BLEND)
|
||||
}) {
|
||||
return Err(
|
||||
GraphicsPipelineCreationError::ColorAttachmentFormatBlendNotSupported {
|
||||
@ -2385,7 +2444,8 @@ where
|
||||
// VUID-VkPipelineColorWriteCreateInfoEXT-pAttachments-04801
|
||||
if !enable && !device.enabled_features().color_write_enable {
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for: "`color_blend_state.attachments` has an element where `color_write_enable` is `StateMode::Fixed(false)`",
|
||||
required_for: "`color_blend_state.attachments` has an element \
|
||||
where `color_write_enable` is `StateMode::Fixed(false)`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
features: &["color_write_enable"],
|
||||
..Default::default()
|
||||
@ -2397,7 +2457,8 @@ where
|
||||
// VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04800
|
||||
if !device.enabled_features().color_write_enable {
|
||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||
required_for: "`color_blend_state.attachments` has an element where `color_write_enable` is `StateMode::Dynamic`",
|
||||
required_for: "`color_blend_state.attachments` has an element \
|
||||
where `color_write_enable` is `StateMode::Dynamic`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
features: &["color_write_enable"],
|
||||
..Default::default()
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user