mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2024-11-25 08:14:20 +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::{
|
device::{
|
||||||
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
||||||
|
QueueFlags,
|
||||||
},
|
},
|
||||||
instance::{Instance, InstanceCreateInfo},
|
instance::{Instance, InstanceCreateInfo},
|
||||||
memory::allocator::StandardMemoryAllocator,
|
memory::allocator::StandardMemoryAllocator,
|
||||||
@ -58,7 +59,7 @@ fn main() {
|
|||||||
// that supports compute operations.
|
// that supports compute operations.
|
||||||
p.queue_family_properties()
|
p.queue_family_properties()
|
||||||
.iter()
|
.iter()
|
||||||
.position(|q| q.queue_flags.compute)
|
.position(|q| q.queue_flags.intersects(QueueFlags::COMPUTE))
|
||||||
.map(|i| (p, i as u32))
|
.map(|i| (p, i as u32))
|
||||||
})
|
})
|
||||||
.min_by_key(|(p, _)| match p.properties().device_type {
|
.min_by_key(|(p, _)| match p.properties().device_type {
|
||||||
@ -157,10 +158,7 @@ fn main() {
|
|||||||
// Builds the buffer and fills it with this iterator.
|
// Builds the buffer and fills it with this iterator.
|
||||||
CpuAccessibleBuffer::from_iter(
|
CpuAccessibleBuffer::from_iter(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::STORAGE_BUFFER,
|
||||||
storage_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
data_iter,
|
data_iter,
|
||||||
)
|
)
|
||||||
|
@ -32,6 +32,7 @@ use vulkano::{
|
|||||||
},
|
},
|
||||||
device::{
|
device::{
|
||||||
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
||||||
|
QueueFlags,
|
||||||
},
|
},
|
||||||
image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage},
|
image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage},
|
||||||
impl_vertex,
|
impl_vertex,
|
||||||
@ -99,7 +100,8 @@ fn main() {
|
|||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.position(|(i, q)| {
|
.position(|(i, q)| {
|
||||||
q.queue_flags.graphics && p.surface_support(i as u32, &surface).unwrap_or(false)
|
q.queue_flags.intersects(QueueFlags::GRAPHICS)
|
||||||
|
&& p.surface_support(i as u32, &surface).unwrap_or(false)
|
||||||
})
|
})
|
||||||
.map(|i| (p, i as u32))
|
.map(|i| (p, i as u32))
|
||||||
})
|
})
|
||||||
@ -155,13 +157,10 @@ fn main() {
|
|||||||
min_image_count: surface_capabilities.min_image_count,
|
min_image_count: surface_capabilities.min_image_count,
|
||||||
image_format,
|
image_format,
|
||||||
image_extent: window.inner_size().into(),
|
image_extent: window.inner_size().into(),
|
||||||
image_usage: ImageUsage {
|
image_usage: ImageUsage::COLOR_ATTACHMENT,
|
||||||
color_attachment: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
},
|
|
||||||
composite_alpha: surface_capabilities
|
composite_alpha: surface_capabilities
|
||||||
.supported_composite_alpha
|
.supported_composite_alpha
|
||||||
.iter()
|
.into_iter()
|
||||||
.next()
|
.next()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -15,6 +15,7 @@ use vulkano::{
|
|||||||
},
|
},
|
||||||
device::{
|
device::{
|
||||||
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
||||||
|
QueueFlags,
|
||||||
},
|
},
|
||||||
image::{view::ImageView, ImageUsage, SwapchainImage},
|
image::{view::ImageView, ImageUsage, SwapchainImage},
|
||||||
instance::{Instance, InstanceCreateInfo},
|
instance::{Instance, InstanceCreateInfo},
|
||||||
@ -68,7 +69,8 @@ fn main() {
|
|||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.position(|(i, q)| {
|
.position(|(i, q)| {
|
||||||
q.queue_flags.graphics && p.surface_support(i as u32, &surface).unwrap_or(false)
|
q.queue_flags.intersects(QueueFlags::GRAPHICS)
|
||||||
|
&& p.surface_support(i as u32, &surface).unwrap_or(false)
|
||||||
})
|
})
|
||||||
.map(|i| (p, i as u32))
|
.map(|i| (p, i as u32))
|
||||||
})
|
})
|
||||||
@ -123,13 +125,10 @@ fn main() {
|
|||||||
min_image_count: surface_capabilities.min_image_count,
|
min_image_count: surface_capabilities.min_image_count,
|
||||||
image_format,
|
image_format,
|
||||||
image_extent: window.inner_size().into(),
|
image_extent: window.inner_size().into(),
|
||||||
image_usage: ImageUsage {
|
image_usage: ImageUsage::COLOR_ATTACHMENT,
|
||||||
color_attachment: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
},
|
|
||||||
composite_alpha: surface_capabilities
|
composite_alpha: surface_capabilities
|
||||||
.supported_composite_alpha
|
.supported_composite_alpha
|
||||||
.iter()
|
.into_iter()
|
||||||
.next()
|
.next()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -87,37 +87,31 @@ fn main() {
|
|||||||
DebugUtilsMessenger::new(
|
DebugUtilsMessenger::new(
|
||||||
instance.clone(),
|
instance.clone(),
|
||||||
DebugUtilsMessengerCreateInfo {
|
DebugUtilsMessengerCreateInfo {
|
||||||
message_severity: DebugUtilsMessageSeverity {
|
message_severity: DebugUtilsMessageSeverity::ERROR
|
||||||
error: true,
|
| DebugUtilsMessageSeverity::WARNING
|
||||||
warning: true,
|
| DebugUtilsMessageSeverity::INFO
|
||||||
information: true,
|
| DebugUtilsMessageSeverity::VERBOSE,
|
||||||
verbose: true,
|
message_type: DebugUtilsMessageType::GENERAL
|
||||||
..DebugUtilsMessageSeverity::empty()
|
| DebugUtilsMessageType::VALIDATION
|
||||||
},
|
| DebugUtilsMessageType::PERFORMANCE,
|
||||||
message_type: DebugUtilsMessageType {
|
|
||||||
general: true,
|
|
||||||
validation: true,
|
|
||||||
performance: true,
|
|
||||||
..DebugUtilsMessageType::empty()
|
|
||||||
},
|
|
||||||
..DebugUtilsMessengerCreateInfo::user_callback(Arc::new(|msg| {
|
..DebugUtilsMessengerCreateInfo::user_callback(Arc::new(|msg| {
|
||||||
let severity = if msg.severity.error {
|
let severity = if msg.severity.intersects(DebugUtilsMessageSeverity::ERROR) {
|
||||||
"error"
|
"error"
|
||||||
} else if msg.severity.warning {
|
} else if msg.severity.intersects(DebugUtilsMessageSeverity::WARNING) {
|
||||||
"warning"
|
"warning"
|
||||||
} else if msg.severity.information {
|
} else if msg.severity.intersects(DebugUtilsMessageSeverity::INFO) {
|
||||||
"information"
|
"information"
|
||||||
} else if msg.severity.verbose {
|
} else if msg.severity.intersects(DebugUtilsMessageSeverity::VERBOSE) {
|
||||||
"verbose"
|
"verbose"
|
||||||
} else {
|
} else {
|
||||||
panic!("no-impl");
|
panic!("no-impl");
|
||||||
};
|
};
|
||||||
|
|
||||||
let ty = if msg.ty.general {
|
let ty = if msg.ty.intersects(DebugUtilsMessageType::GENERAL) {
|
||||||
"general"
|
"general"
|
||||||
} else if msg.ty.validation {
|
} else if msg.ty.intersects(DebugUtilsMessageType::VALIDATION) {
|
||||||
"validation"
|
"validation"
|
||||||
} else if msg.ty.performance {
|
} else if msg.ty.intersects(DebugUtilsMessageType::PERFORMANCE) {
|
||||||
"performance"
|
"performance"
|
||||||
} else {
|
} else {
|
||||||
panic!("no-impl");
|
panic!("no-impl");
|
||||||
|
@ -69,10 +69,7 @@ impl AmbientLightingSystem {
|
|||||||
let vertex_buffer = {
|
let vertex_buffer = {
|
||||||
CpuAccessibleBuffer::from_iter(
|
CpuAccessibleBuffer::from_iter(
|
||||||
memory_allocator,
|
memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::VERTEX_BUFFER,
|
||||||
vertex_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
vertices,
|
vertices,
|
||||||
)
|
)
|
||||||
|
@ -70,10 +70,7 @@ impl DirectionalLightingSystem {
|
|||||||
let vertex_buffer = {
|
let vertex_buffer = {
|
||||||
CpuAccessibleBuffer::from_iter(
|
CpuAccessibleBuffer::from_iter(
|
||||||
memory_allocator,
|
memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::VERTEX_BUFFER,
|
||||||
vertex_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
vertices,
|
vertices,
|
||||||
)
|
)
|
||||||
|
@ -69,10 +69,7 @@ impl PointLightingSystem {
|
|||||||
let vertex_buffer = {
|
let vertex_buffer = {
|
||||||
CpuAccessibleBuffer::from_iter(
|
CpuAccessibleBuffer::from_iter(
|
||||||
memory_allocator,
|
memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::VERTEX_BUFFER,
|
||||||
vertex_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
vertices,
|
vertices,
|
||||||
)
|
)
|
||||||
|
@ -158,11 +158,7 @@ impl FrameSystem {
|
|||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
[1, 1],
|
[1, 1],
|
||||||
Format::A2B10G10R10_UNORM_PACK32,
|
Format::A2B10G10R10_UNORM_PACK32,
|
||||||
ImageUsage {
|
ImageUsage::TRANSIENT_ATTACHMENT | ImageUsage::INPUT_ATTACHMENT,
|
||||||
transient_attachment: true,
|
|
||||||
input_attachment: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
)
|
||||||
@ -172,11 +168,7 @@ impl FrameSystem {
|
|||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
[1, 1],
|
[1, 1],
|
||||||
Format::R16G16B16A16_SFLOAT,
|
Format::R16G16B16A16_SFLOAT,
|
||||||
ImageUsage {
|
ImageUsage::TRANSIENT_ATTACHMENT | ImageUsage::INPUT_ATTACHMENT,
|
||||||
transient_attachment: true,
|
|
||||||
input_attachment: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
)
|
||||||
@ -186,11 +178,7 @@ impl FrameSystem {
|
|||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
[1, 1],
|
[1, 1],
|
||||||
Format::D16_UNORM,
|
Format::D16_UNORM,
|
||||||
ImageUsage {
|
ImageUsage::TRANSIENT_ATTACHMENT | ImageUsage::INPUT_ATTACHMENT,
|
||||||
transient_attachment: true,
|
|
||||||
input_attachment: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
)
|
||||||
@ -280,11 +268,7 @@ impl FrameSystem {
|
|||||||
&self.memory_allocator,
|
&self.memory_allocator,
|
||||||
img_dims,
|
img_dims,
|
||||||
Format::A2B10G10R10_UNORM_PACK32,
|
Format::A2B10G10R10_UNORM_PACK32,
|
||||||
ImageUsage {
|
ImageUsage::TRANSIENT_ATTACHMENT | ImageUsage::INPUT_ATTACHMENT,
|
||||||
transient_attachment: true,
|
|
||||||
input_attachment: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
)
|
||||||
@ -294,11 +278,7 @@ impl FrameSystem {
|
|||||||
&self.memory_allocator,
|
&self.memory_allocator,
|
||||||
img_dims,
|
img_dims,
|
||||||
Format::R16G16B16A16_SFLOAT,
|
Format::R16G16B16A16_SFLOAT,
|
||||||
ImageUsage {
|
ImageUsage::TRANSIENT_ATTACHMENT | ImageUsage::INPUT_ATTACHMENT,
|
||||||
transient_attachment: true,
|
|
||||||
input_attachment: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
)
|
||||||
@ -308,11 +288,7 @@ impl FrameSystem {
|
|||||||
&self.memory_allocator,
|
&self.memory_allocator,
|
||||||
img_dims,
|
img_dims,
|
||||||
Format::D16_UNORM,
|
Format::D16_UNORM,
|
||||||
ImageUsage {
|
ImageUsage::TRANSIENT_ATTACHMENT | ImageUsage::INPUT_ATTACHMENT,
|
||||||
transient_attachment: true,
|
|
||||||
input_attachment: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
)
|
||||||
|
@ -35,6 +35,7 @@ use vulkano::{
|
|||||||
command_buffer::allocator::StandardCommandBufferAllocator,
|
command_buffer::allocator::StandardCommandBufferAllocator,
|
||||||
device::{
|
device::{
|
||||||
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
||||||
|
QueueFlags,
|
||||||
},
|
},
|
||||||
image::{view::ImageView, ImageUsage},
|
image::{view::ImageView, ImageUsage},
|
||||||
instance::{Instance, InstanceCreateInfo},
|
instance::{Instance, InstanceCreateInfo},
|
||||||
@ -90,7 +91,8 @@ fn main() {
|
|||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.position(|(i, q)| {
|
.position(|(i, q)| {
|
||||||
q.queue_flags.graphics && p.surface_support(i as u32, &surface).unwrap_or(false)
|
q.queue_flags.intersects(QueueFlags::GRAPHICS)
|
||||||
|
&& p.surface_support(i as u32, &surface).unwrap_or(false)
|
||||||
})
|
})
|
||||||
.map(|i| (p, i as u32))
|
.map(|i| (p, i as u32))
|
||||||
})
|
})
|
||||||
@ -145,13 +147,10 @@ fn main() {
|
|||||||
min_image_count: surface_capabilities.min_image_count,
|
min_image_count: surface_capabilities.min_image_count,
|
||||||
image_format,
|
image_format,
|
||||||
image_extent: window.inner_size().into(),
|
image_extent: window.inner_size().into(),
|
||||||
image_usage: ImageUsage {
|
image_usage: ImageUsage::COLOR_ATTACHMENT,
|
||||||
color_attachment: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
},
|
|
||||||
composite_alpha: surface_capabilities
|
composite_alpha: surface_capabilities
|
||||||
.supported_composite_alpha
|
.supported_composite_alpha
|
||||||
.iter()
|
.into_iter()
|
||||||
.next()
|
.next()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -60,10 +60,7 @@ impl TriangleDrawSystem {
|
|||||||
let vertex_buffer = {
|
let vertex_buffer = {
|
||||||
CpuAccessibleBuffer::from_iter(
|
CpuAccessibleBuffer::from_iter(
|
||||||
memory_allocator,
|
memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::VERTEX_BUFFER,
|
||||||
vertex_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
vertices,
|
vertices,
|
||||||
)
|
)
|
||||||
|
@ -26,6 +26,7 @@ use vulkano::{
|
|||||||
},
|
},
|
||||||
device::{
|
device::{
|
||||||
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
||||||
|
QueueFlags,
|
||||||
},
|
},
|
||||||
instance::{Instance, InstanceCreateInfo},
|
instance::{Instance, InstanceCreateInfo},
|
||||||
memory::allocator::StandardMemoryAllocator,
|
memory::allocator::StandardMemoryAllocator,
|
||||||
@ -57,7 +58,7 @@ fn main() {
|
|||||||
.filter_map(|p| {
|
.filter_map(|p| {
|
||||||
p.queue_family_properties()
|
p.queue_family_properties()
|
||||||
.iter()
|
.iter()
|
||||||
.position(|q| q.queue_flags.compute)
|
.position(|q| q.queue_flags.intersects(QueueFlags::COMPUTE))
|
||||||
.map(|i| (p, i as u32))
|
.map(|i| (p, i as u32))
|
||||||
})
|
})
|
||||||
.min_by_key(|(p, _)| match p.properties().device_type {
|
.min_by_key(|(p, _)| match p.properties().device_type {
|
||||||
@ -168,10 +169,7 @@ fn main() {
|
|||||||
|
|
||||||
let input_buffer = CpuAccessibleBuffer::from_iter(
|
let input_buffer = CpuAccessibleBuffer::from_iter(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::UNIFORM_BUFFER,
|
||||||
uniform_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
aligned_data.into_iter(),
|
aligned_data.into_iter(),
|
||||||
)
|
)
|
||||||
@ -179,10 +177,7 @@ fn main() {
|
|||||||
|
|
||||||
let output_buffer = CpuAccessibleBuffer::from_iter(
|
let output_buffer = CpuAccessibleBuffer::from_iter(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::STORAGE_BUFFER,
|
||||||
storage_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
(0..12).map(|_| 0u32),
|
(0..12).map(|_| 0u32),
|
||||||
)
|
)
|
||||||
|
@ -26,6 +26,7 @@ use vulkano::{
|
|||||||
},
|
},
|
||||||
device::{
|
device::{
|
||||||
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
||||||
|
QueueFlags,
|
||||||
},
|
},
|
||||||
format::Format,
|
format::Format,
|
||||||
image::{view::ImageView, ImageDimensions, StorageImage},
|
image::{view::ImageView, ImageDimensions, StorageImage},
|
||||||
@ -65,7 +66,7 @@ fn main() {
|
|||||||
.filter_map(|p| {
|
.filter_map(|p| {
|
||||||
p.queue_family_properties()
|
p.queue_family_properties()
|
||||||
.iter()
|
.iter()
|
||||||
.position(|q| q.queue_flags.compute)
|
.position(|q| q.queue_flags.intersects(QueueFlags::COMPUTE))
|
||||||
.map(|i| (p, i as u32))
|
.map(|i| (p, i as u32))
|
||||||
})
|
})
|
||||||
.min_by_key(|(p, _)| match p.properties().device_type {
|
.min_by_key(|(p, _)| match p.properties().device_type {
|
||||||
@ -227,10 +228,7 @@ fn main() {
|
|||||||
|
|
||||||
let buf = CpuAccessibleBuffer::from_iter(
|
let buf = CpuAccessibleBuffer::from_iter(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::TRANSFER_DST,
|
||||||
transfer_dst: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
(0..1024 * 1024 * 4).map(|_| 0u8),
|
(0..1024 * 1024 * 4).map(|_| 0u8),
|
||||||
)
|
)
|
||||||
|
@ -26,7 +26,7 @@ mod linux {
|
|||||||
},
|
},
|
||||||
device::{
|
device::{
|
||||||
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, Queue,
|
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, Queue,
|
||||||
QueueCreateInfo,
|
QueueCreateInfo, QueueFlags,
|
||||||
},
|
},
|
||||||
format::Format,
|
format::Format,
|
||||||
image::{view::ImageView, ImageCreateFlags, ImageUsage, StorageImage, SwapchainImage},
|
image::{view::ImageView, ImageCreateFlags, ImageUsage, StorageImage, SwapchainImage},
|
||||||
@ -107,16 +107,8 @@ mod linux {
|
|||||||
array_layers: 1,
|
array_layers: 1,
|
||||||
},
|
},
|
||||||
Format::R16G16B16A16_UNORM,
|
Format::R16G16B16A16_UNORM,
|
||||||
ImageUsage {
|
ImageUsage::SAMPLED | ImageUsage::TRANSFER_SRC | ImageUsage::TRANSFER_DST,
|
||||||
sampled: true,
|
ImageCreateFlags::MUTABLE_FORMAT,
|
||||||
transfer_src: true,
|
|
||||||
transfer_dst: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
},
|
|
||||||
ImageCreateFlags {
|
|
||||||
mutable_format: true,
|
|
||||||
..ImageCreateFlags::empty()
|
|
||||||
},
|
|
||||||
[queue.queue_family_index()],
|
[queue.queue_family_index()],
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -132,10 +124,7 @@ mod linux {
|
|||||||
Semaphore::new(
|
Semaphore::new(
|
||||||
device.clone(),
|
device.clone(),
|
||||||
SemaphoreCreateInfo {
|
SemaphoreCreateInfo {
|
||||||
export_handle_types: ExternalSemaphoreHandleTypes {
|
export_handle_types: ExternalSemaphoreHandleTypes::OPAQUE_FD,
|
||||||
opaque_fd: true,
|
|
||||||
..ExternalSemaphoreHandleTypes::empty()
|
|
||||||
},
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -145,10 +134,7 @@ mod linux {
|
|||||||
Semaphore::new(
|
Semaphore::new(
|
||||||
device.clone(),
|
device.clone(),
|
||||||
SemaphoreCreateInfo {
|
SemaphoreCreateInfo {
|
||||||
export_handle_types: ExternalSemaphoreHandleTypes {
|
export_handle_types: ExternalSemaphoreHandleTypes::OPAQUE_FD,
|
||||||
opaque_fd: true,
|
|
||||||
..ExternalSemaphoreHandleTypes::empty()
|
|
||||||
},
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -486,7 +472,7 @@ mod linux {
|
|||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.position(|(i, q)| {
|
.position(|(i, q)| {
|
||||||
q.queue_flags.graphics
|
q.queue_flags.intersects(QueueFlags::GRAPHICS)
|
||||||
&& p.surface_support(i as u32, &surface).unwrap_or(false)
|
&& p.surface_support(i as u32, &surface).unwrap_or(false)
|
||||||
})
|
})
|
||||||
.map(|i| (p, i as u32))
|
.map(|i| (p, i as u32))
|
||||||
@ -550,13 +536,10 @@ mod linux {
|
|||||||
min_image_count: surface_capabilities.min_image_count,
|
min_image_count: surface_capabilities.min_image_count,
|
||||||
image_format,
|
image_format,
|
||||||
image_extent: window.inner_size().into(),
|
image_extent: window.inner_size().into(),
|
||||||
image_usage: ImageUsage {
|
image_usage: ImageUsage::COLOR_ATTACHMENT,
|
||||||
color_attachment: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
},
|
|
||||||
composite_alpha: surface_capabilities
|
composite_alpha: surface_capabilities
|
||||||
.supported_composite_alpha
|
.supported_composite_alpha
|
||||||
.iter()
|
.into_iter()
|
||||||
.next()
|
.next()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -583,10 +566,7 @@ mod linux {
|
|||||||
];
|
];
|
||||||
let vertex_buffer = CpuAccessibleBuffer::<[Vertex]>::from_iter(
|
let vertex_buffer = CpuAccessibleBuffer::<[Vertex]>::from_iter(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::VERTEX_BUFFER,
|
||||||
vertex_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
vertices,
|
vertices,
|
||||||
)
|
)
|
||||||
|
@ -22,6 +22,7 @@ use vulkano::{
|
|||||||
},
|
},
|
||||||
device::{
|
device::{
|
||||||
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
||||||
|
QueueFlags,
|
||||||
},
|
},
|
||||||
format::Format,
|
format::Format,
|
||||||
image::{
|
image::{
|
||||||
@ -91,7 +92,8 @@ fn main() {
|
|||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.position(|(i, q)| {
|
.position(|(i, q)| {
|
||||||
q.queue_flags.graphics && p.surface_support(i as u32, &surface).unwrap_or(false)
|
q.queue_flags.intersects(QueueFlags::GRAPHICS)
|
||||||
|
&& p.surface_support(i as u32, &surface).unwrap_or(false)
|
||||||
})
|
})
|
||||||
.map(|i| (p, i as u32))
|
.map(|i| (p, i as u32))
|
||||||
})
|
})
|
||||||
@ -146,13 +148,10 @@ fn main() {
|
|||||||
min_image_count: surface_capabilities.min_image_count,
|
min_image_count: surface_capabilities.min_image_count,
|
||||||
image_format,
|
image_format,
|
||||||
image_extent: window.inner_size().into(),
|
image_extent: window.inner_size().into(),
|
||||||
image_usage: ImageUsage {
|
image_usage: ImageUsage::COLOR_ATTACHMENT,
|
||||||
color_attachment: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
},
|
|
||||||
composite_alpha: surface_capabilities
|
composite_alpha: surface_capabilities
|
||||||
.supported_composite_alpha
|
.supported_composite_alpha
|
||||||
.iter()
|
.into_iter()
|
||||||
.next()
|
.next()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -186,10 +185,7 @@ fn main() {
|
|||||||
];
|
];
|
||||||
let vertex_buffer = CpuAccessibleBuffer::<[Vertex]>::from_iter(
|
let vertex_buffer = CpuAccessibleBuffer::<[Vertex]>::from_iter(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::VERTEX_BUFFER,
|
||||||
vertex_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
vertices,
|
vertices,
|
||||||
)
|
)
|
||||||
@ -250,10 +246,7 @@ fn main() {
|
|||||||
|
|
||||||
let buffer = CpuAccessibleBuffer::from_iter(
|
let buffer = CpuAccessibleBuffer::from_iter(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::TRANSFER_SRC,
|
||||||
transfer_src: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
image_data,
|
image_data,
|
||||||
)
|
)
|
||||||
|
@ -20,6 +20,7 @@ use vulkano::{
|
|||||||
},
|
},
|
||||||
device::{
|
device::{
|
||||||
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
||||||
|
QueueFlags,
|
||||||
},
|
},
|
||||||
format::Format,
|
format::Format,
|
||||||
image::{
|
image::{
|
||||||
@ -89,7 +90,8 @@ fn main() {
|
|||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.position(|(i, q)| {
|
.position(|(i, q)| {
|
||||||
q.queue_flags.graphics && p.surface_support(i as u32, &surface).unwrap_or(false)
|
q.queue_flags.intersects(QueueFlags::GRAPHICS)
|
||||||
|
&& p.surface_support(i as u32, &surface).unwrap_or(false)
|
||||||
})
|
})
|
||||||
.map(|i| (p, i as u32))
|
.map(|i| (p, i as u32))
|
||||||
})
|
})
|
||||||
@ -144,13 +146,10 @@ fn main() {
|
|||||||
min_image_count: surface_capabilities.min_image_count,
|
min_image_count: surface_capabilities.min_image_count,
|
||||||
image_format,
|
image_format,
|
||||||
image_extent: window.inner_size().into(),
|
image_extent: window.inner_size().into(),
|
||||||
image_usage: ImageUsage {
|
image_usage: ImageUsage::COLOR_ATTACHMENT,
|
||||||
color_attachment: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
},
|
|
||||||
composite_alpha: surface_capabilities
|
composite_alpha: surface_capabilities
|
||||||
.supported_composite_alpha
|
.supported_composite_alpha
|
||||||
.iter()
|
.into_iter()
|
||||||
.next()
|
.next()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -184,10 +183,7 @@ fn main() {
|
|||||||
];
|
];
|
||||||
let vertex_buffer = CpuAccessibleBuffer::<[Vertex]>::from_iter(
|
let vertex_buffer = CpuAccessibleBuffer::<[Vertex]>::from_iter(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::VERTEX_BUFFER,
|
||||||
vertex_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
vertices,
|
vertices,
|
||||||
)
|
)
|
||||||
|
@ -29,6 +29,7 @@ use vulkano::{
|
|||||||
},
|
},
|
||||||
device::{
|
device::{
|
||||||
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
||||||
|
QueueFlags,
|
||||||
},
|
},
|
||||||
format::Format,
|
format::Format,
|
||||||
image::{
|
image::{
|
||||||
@ -95,7 +96,8 @@ fn main() {
|
|||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.position(|(i, q)| {
|
.position(|(i, q)| {
|
||||||
q.queue_flags.graphics && p.surface_support(i as u32, &surface).unwrap_or(false)
|
q.queue_flags.intersects(QueueFlags::GRAPHICS)
|
||||||
|
&& p.surface_support(i as u32, &surface).unwrap_or(false)
|
||||||
})
|
})
|
||||||
.map(|i| (p, i as u32))
|
.map(|i| (p, i as u32))
|
||||||
})
|
})
|
||||||
@ -150,13 +152,10 @@ fn main() {
|
|||||||
min_image_count: surface_capabilities.min_image_count,
|
min_image_count: surface_capabilities.min_image_count,
|
||||||
image_format,
|
image_format,
|
||||||
image_extent: window.inner_size().into(),
|
image_extent: window.inner_size().into(),
|
||||||
image_usage: ImageUsage {
|
image_usage: ImageUsage::COLOR_ATTACHMENT,
|
||||||
color_attachment: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
},
|
|
||||||
composite_alpha: surface_capabilities
|
composite_alpha: surface_capabilities
|
||||||
.supported_composite_alpha
|
.supported_composite_alpha
|
||||||
.iter()
|
.into_iter()
|
||||||
.next()
|
.next()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -190,10 +189,7 @@ fn main() {
|
|||||||
];
|
];
|
||||||
let vertex_buffer = CpuAccessibleBuffer::<[Vertex]>::from_iter(
|
let vertex_buffer = CpuAccessibleBuffer::<[Vertex]>::from_iter(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::VERTEX_BUFFER,
|
||||||
vertex_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
vertices,
|
vertices,
|
||||||
)
|
)
|
||||||
|
@ -37,6 +37,7 @@ use vulkano::{
|
|||||||
},
|
},
|
||||||
device::{
|
device::{
|
||||||
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
||||||
|
QueueFlags,
|
||||||
},
|
},
|
||||||
image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage},
|
image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage},
|
||||||
impl_vertex,
|
impl_vertex,
|
||||||
@ -108,7 +109,8 @@ fn main() {
|
|||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.position(|(i, q)| {
|
.position(|(i, q)| {
|
||||||
q.queue_flags.graphics && p.surface_support(i as u32, &surface).unwrap_or(false)
|
q.queue_flags.intersects(QueueFlags::GRAPHICS)
|
||||||
|
&& p.surface_support(i as u32, &surface).unwrap_or(false)
|
||||||
})
|
})
|
||||||
.map(|i| (p, i as u32))
|
.map(|i| (p, i as u32))
|
||||||
})
|
})
|
||||||
@ -164,13 +166,10 @@ fn main() {
|
|||||||
min_image_count: surface_capabilities.min_image_count,
|
min_image_count: surface_capabilities.min_image_count,
|
||||||
image_format,
|
image_format,
|
||||||
image_extent: window.inner_size().into(),
|
image_extent: window.inner_size().into(),
|
||||||
image_usage: ImageUsage {
|
image_usage: ImageUsage::COLOR_ATTACHMENT,
|
||||||
color_attachment: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
},
|
|
||||||
composite_alpha: surface_capabilities
|
composite_alpha: surface_capabilities
|
||||||
.supported_composite_alpha
|
.supported_composite_alpha
|
||||||
.iter()
|
.into_iter()
|
||||||
.next()
|
.next()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -261,20 +260,12 @@ fn main() {
|
|||||||
// set the number of vertices to draw
|
// set the number of vertices to draw
|
||||||
let indirect_args_pool: CpuBufferPool<DrawIndirectCommand> = CpuBufferPool::new(
|
let indirect_args_pool: CpuBufferPool<DrawIndirectCommand> = CpuBufferPool::new(
|
||||||
memory_allocator.clone(),
|
memory_allocator.clone(),
|
||||||
BufferUsage {
|
BufferUsage::INDIRECT_BUFFER | BufferUsage::STORAGE_BUFFER,
|
||||||
indirect_buffer: true,
|
|
||||||
storage_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
MemoryUsage::Upload,
|
MemoryUsage::Upload,
|
||||||
);
|
);
|
||||||
let vertex_pool: CpuBufferPool<Vertex> = CpuBufferPool::new(
|
let vertex_pool: CpuBufferPool<Vertex> = CpuBufferPool::new(
|
||||||
memory_allocator,
|
memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::STORAGE_BUFFER | BufferUsage::VERTEX_BUFFER,
|
||||||
storage_buffer: true,
|
|
||||||
vertex_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
MemoryUsage::Upload,
|
MemoryUsage::Upload,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ use vulkano::{
|
|||||||
},
|
},
|
||||||
device::{
|
device::{
|
||||||
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
||||||
|
QueueFlags,
|
||||||
},
|
},
|
||||||
image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage},
|
image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage},
|
||||||
impl_vertex,
|
impl_vertex,
|
||||||
@ -105,7 +106,8 @@ fn main() {
|
|||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.position(|(i, q)| {
|
.position(|(i, q)| {
|
||||||
q.queue_flags.graphics && p.surface_support(i as u32, &surface).unwrap_or(false)
|
q.queue_flags.intersects(QueueFlags::GRAPHICS)
|
||||||
|
&& p.surface_support(i as u32, &surface).unwrap_or(false)
|
||||||
})
|
})
|
||||||
.map(|i| (p, i as u32))
|
.map(|i| (p, i as u32))
|
||||||
})
|
})
|
||||||
@ -161,13 +163,10 @@ fn main() {
|
|||||||
min_image_count: surface_capabilities.min_image_count,
|
min_image_count: surface_capabilities.min_image_count,
|
||||||
image_format,
|
image_format,
|
||||||
image_extent: window.inner_size().into(),
|
image_extent: window.inner_size().into(),
|
||||||
image_usage: ImageUsage {
|
image_usage: ImageUsage::COLOR_ATTACHMENT,
|
||||||
color_attachment: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
},
|
|
||||||
composite_alpha: surface_capabilities
|
composite_alpha: surface_capabilities
|
||||||
.supported_composite_alpha
|
.supported_composite_alpha
|
||||||
.iter()
|
.into_iter()
|
||||||
.next()
|
.next()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -194,10 +193,7 @@ fn main() {
|
|||||||
let vertex_buffer = {
|
let vertex_buffer = {
|
||||||
CpuAccessibleBuffer::from_iter(
|
CpuAccessibleBuffer::from_iter(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::VERTEX_BUFFER,
|
||||||
vertex_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
vertices,
|
vertices,
|
||||||
)
|
)
|
||||||
@ -229,10 +225,7 @@ fn main() {
|
|||||||
};
|
};
|
||||||
let instance_buffer = CpuAccessibleBuffer::from_iter(
|
let instance_buffer = CpuAccessibleBuffer::from_iter(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::VERTEX_BUFFER,
|
||||||
vertex_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
instances,
|
instances,
|
||||||
)
|
)
|
||||||
|
@ -57,10 +57,7 @@ impl FractalComputePipeline {
|
|||||||
let palette_size = colors.len() as i32;
|
let palette_size = colors.len() as i32;
|
||||||
let palette = CpuAccessibleBuffer::from_iter(
|
let palette = CpuAccessibleBuffer::from_iter(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::STORAGE_BUFFER,
|
||||||
storage_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
colors,
|
colors,
|
||||||
)
|
)
|
||||||
@ -103,10 +100,7 @@ impl FractalComputePipeline {
|
|||||||
}
|
}
|
||||||
self.palette = CpuAccessibleBuffer::from_iter(
|
self.palette = CpuAccessibleBuffer::from_iter(
|
||||||
&self.memory_allocator,
|
&self.memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::STORAGE_BUFFER,
|
||||||
storage_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
colors.into_iter(),
|
colors.into_iter(),
|
||||||
)
|
)
|
||||||
|
@ -57,13 +57,10 @@ fn main() {
|
|||||||
primary_window_renderer.add_additional_image_view(
|
primary_window_renderer.add_additional_image_view(
|
||||||
render_target_id,
|
render_target_id,
|
||||||
DEFAULT_IMAGE_FORMAT,
|
DEFAULT_IMAGE_FORMAT,
|
||||||
ImageUsage {
|
ImageUsage::SAMPLED
|
||||||
sampled: true,
|
| ImageUsage::STORAGE
|
||||||
storage: true,
|
| ImageUsage::COLOR_ATTACHMENT
|
||||||
color_attachment: true,
|
| ImageUsage::TRANSFER_DST,
|
||||||
transfer_dst: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Create app to hold the logic of our fractal explorer
|
// Create app to hold the logic of our fractal explorer
|
||||||
|
@ -89,20 +89,14 @@ impl PixelsDrawPipeline {
|
|||||||
let (vertices, indices) = textured_quad(2.0, 2.0);
|
let (vertices, indices) = textured_quad(2.0, 2.0);
|
||||||
let vertex_buffer = CpuAccessibleBuffer::<[TexturedVertex]>::from_iter(
|
let vertex_buffer = CpuAccessibleBuffer::<[TexturedVertex]>::from_iter(
|
||||||
memory_allocator,
|
memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::VERTEX_BUFFER,
|
||||||
vertex_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
vertices,
|
vertices,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let index_buffer = CpuAccessibleBuffer::<[u32]>::from_iter(
|
let index_buffer = CpuAccessibleBuffer::<[u32]>::from_iter(
|
||||||
memory_allocator,
|
memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::INDEX_BUFFER,
|
||||||
index_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
indices,
|
indices,
|
||||||
)
|
)
|
||||||
|
@ -74,6 +74,7 @@ use vulkano::{
|
|||||||
},
|
},
|
||||||
device::{
|
device::{
|
||||||
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
||||||
|
QueueFlags,
|
||||||
},
|
},
|
||||||
format::Format,
|
format::Format,
|
||||||
image::{view::ImageView, AttachmentImage, ImageDimensions, SampleCount, StorageImage},
|
image::{view::ImageView, AttachmentImage, ImageDimensions, SampleCount, StorageImage},
|
||||||
@ -119,7 +120,7 @@ fn main() {
|
|||||||
.filter_map(|p| {
|
.filter_map(|p| {
|
||||||
p.queue_family_properties()
|
p.queue_family_properties()
|
||||||
.iter()
|
.iter()
|
||||||
.position(|q| q.queue_flags.graphics)
|
.position(|q| q.queue_flags.intersects(QueueFlags::GRAPHICS))
|
||||||
.map(|i| (p, i as u32))
|
.map(|i| (p, i as u32))
|
||||||
})
|
})
|
||||||
.min_by_key(|(p, _)| match p.properties().device_type {
|
.min_by_key(|(p, _)| match p.properties().device_type {
|
||||||
@ -288,10 +289,7 @@ fn main() {
|
|||||||
];
|
];
|
||||||
let vertex_buffer = CpuAccessibleBuffer::from_iter(
|
let vertex_buffer = CpuAccessibleBuffer::from_iter(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::VERTEX_BUFFER,
|
||||||
vertex_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
vertices,
|
vertices,
|
||||||
)
|
)
|
||||||
@ -321,10 +319,7 @@ fn main() {
|
|||||||
|
|
||||||
let buf = CpuAccessibleBuffer::from_iter(
|
let buf = CpuAccessibleBuffer::from_iter(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::TRANSFER_DST,
|
||||||
transfer_dst: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
(0..1024 * 1024 * 4).map(|_| 0u8),
|
(0..1024 * 1024 * 4).map(|_| 0u8),
|
||||||
)
|
)
|
||||||
|
@ -26,6 +26,7 @@ use vulkano::{
|
|||||||
},
|
},
|
||||||
device::{
|
device::{
|
||||||
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
||||||
|
QueueFlags,
|
||||||
},
|
},
|
||||||
image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage},
|
image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage},
|
||||||
impl_vertex,
|
impl_vertex,
|
||||||
@ -105,7 +106,7 @@ fn main() {
|
|||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.position(|(i, q)| {
|
.position(|(i, q)| {
|
||||||
q.queue_flags.graphics
|
q.queue_flags.intersects(QueueFlags::GRAPHICS)
|
||||||
&& p.surface_support(i as u32, &surface).unwrap_or(false)
|
&& p.surface_support(i as u32, &surface).unwrap_or(false)
|
||||||
})
|
})
|
||||||
.map(|i| (p, i as u32))
|
.map(|i| (p, i as u32))
|
||||||
@ -166,13 +167,10 @@ fn main() {
|
|||||||
min_image_count: surface_caps.min_image_count,
|
min_image_count: surface_caps.min_image_count,
|
||||||
image_format,
|
image_format,
|
||||||
image_extent: window.inner_size().into(),
|
image_extent: window.inner_size().into(),
|
||||||
image_usage: ImageUsage {
|
image_usage: ImageUsage::COLOR_ATTACHMENT,
|
||||||
color_attachment: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
},
|
|
||||||
composite_alpha: surface_caps
|
composite_alpha: surface_caps
|
||||||
.supported_composite_alpha
|
.supported_composite_alpha
|
||||||
.iter()
|
.into_iter()
|
||||||
.next()
|
.next()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -203,10 +201,7 @@ fn main() {
|
|||||||
];
|
];
|
||||||
let vertex_buffer = CpuAccessibleBuffer::from_iter(
|
let vertex_buffer = CpuAccessibleBuffer::from_iter(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::VERTEX_BUFFER,
|
||||||
vertex_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
vertices,
|
vertices,
|
||||||
)
|
)
|
||||||
@ -329,7 +324,7 @@ fn main() {
|
|||||||
let (swapchain, images) = {
|
let (swapchain, images) = {
|
||||||
let composite_alpha = surface_caps
|
let composite_alpha = surface_caps
|
||||||
.supported_composite_alpha
|
.supported_composite_alpha
|
||||||
.iter()
|
.into_iter()
|
||||||
.next()
|
.next()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let image_format = Some(
|
let image_format = Some(
|
||||||
@ -347,10 +342,7 @@ fn main() {
|
|||||||
min_image_count: surface_caps.min_image_count,
|
min_image_count: surface_caps.min_image_count,
|
||||||
image_format,
|
image_format,
|
||||||
image_extent: window.inner_size().into(),
|
image_extent: window.inner_size().into(),
|
||||||
image_usage: ImageUsage {
|
image_usage: ImageUsage::COLOR_ATTACHMENT,
|
||||||
color_attachment: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
},
|
|
||||||
composite_alpha,
|
composite_alpha,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
|
@ -47,10 +47,7 @@ fn rand_grid(
|
|||||||
) -> Arc<CpuAccessibleBuffer<[u32]>> {
|
) -> Arc<CpuAccessibleBuffer<[u32]>> {
|
||||||
CpuAccessibleBuffer::from_iter(
|
CpuAccessibleBuffer::from_iter(
|
||||||
memory_allocator,
|
memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::STORAGE_BUFFER,
|
||||||
storage_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
(0..(size[0] * size[1]))
|
(0..(size[0] * size[1]))
|
||||||
.map(|_| rand::thread_rng().gen_range(0u32..=1))
|
.map(|_| rand::thread_rng().gen_range(0u32..=1))
|
||||||
@ -87,13 +84,10 @@ impl GameOfLifeComputePipeline {
|
|||||||
compute_queue.clone(),
|
compute_queue.clone(),
|
||||||
size,
|
size,
|
||||||
Format::R8G8B8A8_UNORM,
|
Format::R8G8B8A8_UNORM,
|
||||||
ImageUsage {
|
ImageUsage::SAMPLED
|
||||||
sampled: true,
|
| ImageUsage::STORAGE
|
||||||
storage: true,
|
| ImageUsage::COLOR_ATTACHMENT
|
||||||
color_attachment: true,
|
| ImageUsage::TRANSFER_DST,
|
||||||
transfer_dst: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -89,20 +89,14 @@ impl PixelsDrawPipeline {
|
|||||||
let (vertices, indices) = textured_quad(2.0, 2.0);
|
let (vertices, indices) = textured_quad(2.0, 2.0);
|
||||||
let vertex_buffer = CpuAccessibleBuffer::<[TexturedVertex]>::from_iter(
|
let vertex_buffer = CpuAccessibleBuffer::<[TexturedVertex]>::from_iter(
|
||||||
memory_allocator,
|
memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::VERTEX_BUFFER,
|
||||||
vertex_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
vertices.into_iter(),
|
vertices.into_iter(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let index_buffer = CpuAccessibleBuffer::<[u32]>::from_iter(
|
let index_buffer = CpuAccessibleBuffer::<[u32]>::from_iter(
|
||||||
memory_allocator,
|
memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::INDEX_BUFFER,
|
||||||
index_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
indices.into_iter(),
|
indices.into_iter(),
|
||||||
)
|
)
|
||||||
|
@ -23,7 +23,7 @@ use vulkano::{
|
|||||||
},
|
},
|
||||||
device::{
|
device::{
|
||||||
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, Features,
|
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, Features,
|
||||||
QueueCreateInfo,
|
QueueCreateInfo, QueueFlags,
|
||||||
},
|
},
|
||||||
format::Format,
|
format::Format,
|
||||||
image::{
|
image::{
|
||||||
@ -93,7 +93,7 @@ fn main() {
|
|||||||
.filter_map(|p| {
|
.filter_map(|p| {
|
||||||
p.queue_family_properties()
|
p.queue_family_properties()
|
||||||
.iter()
|
.iter()
|
||||||
.position(|q| q.queue_flags.graphics)
|
.position(|q| q.queue_flags.intersects(QueueFlags::GRAPHICS))
|
||||||
.map(|i| (p, i as u32))
|
.map(|i| (p, i as u32))
|
||||||
})
|
})
|
||||||
.min_by_key(|(p, _)| match p.properties().device_type {
|
.min_by_key(|(p, _)| match p.properties().device_type {
|
||||||
@ -140,11 +140,7 @@ fn main() {
|
|||||||
array_layers: 2,
|
array_layers: 2,
|
||||||
},
|
},
|
||||||
Format::B8G8R8A8_SRGB,
|
Format::B8G8R8A8_SRGB,
|
||||||
ImageUsage {
|
ImageUsage::TRANSFER_SRC | ImageUsage::COLOR_ATTACHMENT,
|
||||||
transfer_src: true,
|
|
||||||
color_attachment: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
},
|
|
||||||
ImageCreateFlags::empty(),
|
ImageCreateFlags::empty(),
|
||||||
Some(queue.queue_family_index()),
|
Some(queue.queue_family_index()),
|
||||||
)
|
)
|
||||||
@ -172,10 +168,7 @@ fn main() {
|
|||||||
];
|
];
|
||||||
let vertex_buffer = CpuAccessibleBuffer::from_iter(
|
let vertex_buffer = CpuAccessibleBuffer::from_iter(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::VERTEX_BUFFER,
|
||||||
vertex_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
vertices,
|
vertices,
|
||||||
)
|
)
|
||||||
@ -286,10 +279,7 @@ fn main() {
|
|||||||
let create_buffer = || {
|
let create_buffer = || {
|
||||||
CpuAccessibleBuffer::from_iter(
|
CpuAccessibleBuffer::from_iter(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::TRANSFER_DST,
|
||||||
transfer_dst: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
(0..image.dimensions().width() * image.dimensions().height() * 4).map(|_| 0u8),
|
(0..image.dimensions().width() * image.dimensions().height() * 4).map(|_| 0u8),
|
||||||
)
|
)
|
||||||
|
@ -21,6 +21,7 @@ use vulkano::{
|
|||||||
},
|
},
|
||||||
device::{
|
device::{
|
||||||
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
||||||
|
QueueFlags,
|
||||||
},
|
},
|
||||||
format::Format,
|
format::Format,
|
||||||
image::{view::ImageView, AttachmentImage, ImageAccess, ImageUsage, SwapchainImage},
|
image::{view::ImageView, AttachmentImage, ImageAccess, ImageUsage, SwapchainImage},
|
||||||
@ -84,7 +85,8 @@ fn main() {
|
|||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.position(|(i, q)| {
|
.position(|(i, q)| {
|
||||||
q.queue_flags.graphics && p.surface_support(i as u32, &surface).unwrap_or(false)
|
q.queue_flags.intersects(QueueFlags::GRAPHICS)
|
||||||
|
&& p.surface_support(i as u32, &surface).unwrap_or(false)
|
||||||
})
|
})
|
||||||
.map(|i| (p, i as u32))
|
.map(|i| (p, i as u32))
|
||||||
})
|
})
|
||||||
@ -139,13 +141,10 @@ fn main() {
|
|||||||
min_image_count: surface_capabilities.min_image_count,
|
min_image_count: surface_capabilities.min_image_count,
|
||||||
image_format,
|
image_format,
|
||||||
image_extent: window.inner_size().into(),
|
image_extent: window.inner_size().into(),
|
||||||
image_usage: ImageUsage {
|
image_usage: ImageUsage::COLOR_ATTACHMENT,
|
||||||
color_attachment: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
},
|
|
||||||
composite_alpha: surface_capabilities
|
composite_alpha: surface_capabilities
|
||||||
.supported_composite_alpha
|
.supported_composite_alpha
|
||||||
.iter()
|
.into_iter()
|
||||||
.next()
|
.next()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -212,10 +211,7 @@ fn main() {
|
|||||||
];
|
];
|
||||||
let vertex_buffer = CpuAccessibleBuffer::from_iter(
|
let vertex_buffer = CpuAccessibleBuffer::from_iter(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::VERTEX_BUFFER,
|
||||||
vertex_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
vertices,
|
vertices,
|
||||||
)
|
)
|
||||||
@ -421,15 +417,13 @@ fn main() {
|
|||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
// Begin query 0, then draw the red triangle.
|
// Begin query 0, then draw the red triangle.
|
||||||
// Enabling the `precise` bit would give exact numeric results. This needs
|
// Enabling the `QueryControlFlags::PRECISE` flag would give exact numeric
|
||||||
// the `occlusion_query_precise` feature to be enabled on the device.
|
// results. This needs the `occlusion_query_precise` feature to be enabled on
|
||||||
|
// the device.
|
||||||
.begin_query(
|
.begin_query(
|
||||||
query_pool.clone(),
|
query_pool.clone(),
|
||||||
0,
|
0,
|
||||||
QueryControlFlags {
|
QueryControlFlags::empty(), // QueryControlFlags::PRECISE
|
||||||
precise: false,
|
|
||||||
..QueryControlFlags::empty()
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.bind_vertex_buffers(0, triangle1.clone())
|
.bind_vertex_buffers(0, triangle1.clone())
|
||||||
@ -439,14 +433,7 @@ fn main() {
|
|||||||
.end_query(query_pool.clone(), 0)
|
.end_query(query_pool.clone(), 0)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
// Begin query 1 for the cyan triangle.
|
// Begin query 1 for the cyan triangle.
|
||||||
.begin_query(
|
.begin_query(query_pool.clone(), 1, QueryControlFlags::empty())
|
||||||
query_pool.clone(),
|
|
||||||
1,
|
|
||||||
QueryControlFlags {
|
|
||||||
precise: false,
|
|
||||||
..QueryControlFlags::empty()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.bind_vertex_buffers(0, triangle2.clone())
|
.bind_vertex_buffers(0, triangle2.clone())
|
||||||
.draw(triangle2.len() as u32, 1, 0, 0)
|
.draw(triangle2.len() as u32, 1, 0, 0)
|
||||||
@ -454,14 +441,7 @@ fn main() {
|
|||||||
.end_query(query_pool.clone(), 1)
|
.end_query(query_pool.clone(), 1)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
// Finally, query 2 for the green triangle.
|
// Finally, query 2 for the green triangle.
|
||||||
.begin_query(
|
.begin_query(query_pool.clone(), 2, QueryControlFlags::empty())
|
||||||
query_pool.clone(),
|
|
||||||
2,
|
|
||||||
QueryControlFlags {
|
|
||||||
precise: false,
|
|
||||||
..QueryControlFlags::empty()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.bind_vertex_buffers(0, triangle3.clone())
|
.bind_vertex_buffers(0, triangle3.clone())
|
||||||
.draw(triangle3.len() as u32, 1, 0, 0)
|
.draw(triangle3.len() as u32, 1, 0, 0)
|
||||||
@ -505,30 +485,29 @@ fn main() {
|
|||||||
// `copy_query_pool_results` function on a command buffer to write results to a
|
// `copy_query_pool_results` function on a command buffer to write results to a
|
||||||
// Vulkano buffer. This could then be used to influence draw operations further down
|
// Vulkano buffer. This could then be used to influence draw operations further down
|
||||||
// the line, either in the same frame or a future frame.
|
// the line, either in the same frame or a future frame.
|
||||||
|
#[rustfmt::skip]
|
||||||
query_pool
|
query_pool
|
||||||
.queries_range(0..3)
|
.queries_range(0..3)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.get_results(
|
.get_results(
|
||||||
&mut query_results,
|
&mut query_results,
|
||||||
QueryResultFlags {
|
// Block the function call until the results are available.
|
||||||
// Block the function call until the results are available.
|
// Note: if not all the queries have actually been executed, then this
|
||||||
// Note: if not all the queries have actually been executed, then this
|
// will wait forever for something that never happens!
|
||||||
// will wait forever for something that never happens!
|
QueryResultFlags::WAIT
|
||||||
wait: true,
|
|
||||||
|
|
||||||
// Blocking and waiting will never give partial results.
|
// Enable this flag to give partial results if available, instead of waiting
|
||||||
partial: false,
|
// for the full results.
|
||||||
|
// | QueryResultFlags::PARTIAL
|
||||||
|
|
||||||
// Blocking and waiting will ensure the results are always available after
|
// Blocking and waiting will ensure the results are always available after
|
||||||
// the function returns.
|
// the function returns.
|
||||||
//
|
//
|
||||||
// If you disable waiting, then this can be used to include the
|
// If you disable waiting, then this flag can be enabled to include the
|
||||||
// availability of each query's results. You need one extra element per
|
// availability of each query's results. You need one extra element per
|
||||||
// query in your `query_results` buffer for this. This element will
|
// query in your `query_results` buffer for this. This element will
|
||||||
// be filled with a zero/nonzero value indicating availability.
|
// be filled with a zero/nonzero value indicating availability.
|
||||||
with_availability: false,
|
// | QueryResultFlags::WITH_AVAILABILITY
|
||||||
..QueryResultFlags::empty()
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@ -564,11 +543,7 @@ fn window_size_dependent_setup(
|
|||||||
memory_allocator,
|
memory_allocator,
|
||||||
dimensions,
|
dimensions,
|
||||||
Format::D16_UNORM,
|
Format::D16_UNORM,
|
||||||
ImageUsage {
|
ImageUsage::DEPTH_STENCIL_ATTACHMENT | ImageUsage::TRANSIENT_ATTACHMENT,
|
||||||
depth_stencil_attachment: true,
|
|
||||||
transient_attachment: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
)
|
||||||
|
@ -34,6 +34,7 @@ use std::{
|
|||||||
use vulkano::{
|
use vulkano::{
|
||||||
device::{
|
device::{
|
||||||
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
||||||
|
QueueFlags,
|
||||||
},
|
},
|
||||||
instance::{Instance, InstanceCreateInfo},
|
instance::{Instance, InstanceCreateInfo},
|
||||||
pipeline::{cache::PipelineCache, ComputePipeline},
|
pipeline::{cache::PipelineCache, ComputePipeline},
|
||||||
@ -65,7 +66,7 @@ fn main() {
|
|||||||
.filter_map(|p| {
|
.filter_map(|p| {
|
||||||
p.queue_family_properties()
|
p.queue_family_properties()
|
||||||
.iter()
|
.iter()
|
||||||
.position(|q| q.queue_flags.compute)
|
.position(|q| q.queue_flags.intersects(QueueFlags::COMPUTE))
|
||||||
.map(|i| (p, i as u32))
|
.map(|i| (p, i as u32))
|
||||||
})
|
})
|
||||||
.min_by_key(|(p, _)| match p.properties().device_type {
|
.min_by_key(|(p, _)| match p.properties().device_type {
|
||||||
|
@ -22,6 +22,7 @@ use vulkano::{
|
|||||||
},
|
},
|
||||||
device::{
|
device::{
|
||||||
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
||||||
|
QueueFlags,
|
||||||
},
|
},
|
||||||
instance::{Instance, InstanceCreateInfo},
|
instance::{Instance, InstanceCreateInfo},
|
||||||
memory::allocator::StandardMemoryAllocator,
|
memory::allocator::StandardMemoryAllocator,
|
||||||
@ -53,7 +54,7 @@ fn main() {
|
|||||||
.filter_map(|p| {
|
.filter_map(|p| {
|
||||||
p.queue_family_properties()
|
p.queue_family_properties()
|
||||||
.iter()
|
.iter()
|
||||||
.position(|q| q.queue_flags.compute)
|
.position(|q| q.queue_flags.intersects(QueueFlags::COMPUTE))
|
||||||
.map(|i| (p, i as u32))
|
.map(|i| (p, i as u32))
|
||||||
})
|
})
|
||||||
.min_by_key(|(p, _)| match p.properties().device_type {
|
.min_by_key(|(p, _)| match p.properties().device_type {
|
||||||
@ -139,10 +140,7 @@ fn main() {
|
|||||||
let data_iter = 0..65536u32;
|
let data_iter = 0..65536u32;
|
||||||
CpuAccessibleBuffer::from_iter(
|
CpuAccessibleBuffer::from_iter(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::STORAGE_BUFFER,
|
||||||
storage_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
data_iter,
|
data_iter,
|
||||||
)
|
)
|
||||||
|
@ -18,6 +18,7 @@ use vulkano::{
|
|||||||
descriptor_set::WriteDescriptorSet,
|
descriptor_set::WriteDescriptorSet,
|
||||||
device::{
|
device::{
|
||||||
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
||||||
|
QueueFlags,
|
||||||
},
|
},
|
||||||
format::Format,
|
format::Format,
|
||||||
image::{
|
image::{
|
||||||
@ -85,7 +86,8 @@ fn main() {
|
|||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.position(|(i, q)| {
|
.position(|(i, q)| {
|
||||||
q.queue_flags.graphics && p.surface_support(i as u32, &surface).unwrap_or(false)
|
q.queue_flags.intersects(QueueFlags::GRAPHICS)
|
||||||
|
&& p.surface_support(i as u32, &surface).unwrap_or(false)
|
||||||
})
|
})
|
||||||
.map(|i| (p, i as u32))
|
.map(|i| (p, i as u32))
|
||||||
})
|
})
|
||||||
@ -140,13 +142,10 @@ fn main() {
|
|||||||
min_image_count: surface_capabilities.min_image_count,
|
min_image_count: surface_capabilities.min_image_count,
|
||||||
image_format,
|
image_format,
|
||||||
image_extent: window.inner_size().into(),
|
image_extent: window.inner_size().into(),
|
||||||
image_usage: ImageUsage {
|
image_usage: ImageUsage::COLOR_ATTACHMENT,
|
||||||
color_attachment: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
},
|
|
||||||
composite_alpha: surface_capabilities
|
composite_alpha: surface_capabilities
|
||||||
.supported_composite_alpha
|
.supported_composite_alpha
|
||||||
.iter()
|
.into_iter()
|
||||||
.next()
|
.next()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -180,10 +179,7 @@ fn main() {
|
|||||||
];
|
];
|
||||||
let vertex_buffer = CpuAccessibleBuffer::<[Vertex]>::from_iter(
|
let vertex_buffer = CpuAccessibleBuffer::<[Vertex]>::from_iter(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::VERTEX_BUFFER,
|
||||||
vertex_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
vertices,
|
vertices,
|
||||||
)
|
)
|
||||||
|
@ -29,6 +29,7 @@ use vulkano::{
|
|||||||
},
|
},
|
||||||
device::{
|
device::{
|
||||||
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
||||||
|
QueueFlags,
|
||||||
},
|
},
|
||||||
image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage},
|
image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage},
|
||||||
impl_vertex,
|
impl_vertex,
|
||||||
@ -100,7 +101,8 @@ fn main() {
|
|||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.position(|(i, q)| {
|
.position(|(i, q)| {
|
||||||
q.queue_flags.graphics && p.surface_support(i as u32, &surface).unwrap_or(false)
|
q.queue_flags.intersects(QueueFlags::GRAPHICS)
|
||||||
|
&& p.surface_support(i as u32, &surface).unwrap_or(false)
|
||||||
})
|
})
|
||||||
.map(|i| (p, i as u32))
|
.map(|i| (p, i as u32))
|
||||||
})
|
})
|
||||||
@ -155,13 +157,10 @@ fn main() {
|
|||||||
min_image_count: surface_capabilities.min_image_count,
|
min_image_count: surface_capabilities.min_image_count,
|
||||||
image_format,
|
image_format,
|
||||||
image_extent: window.inner_size().into(),
|
image_extent: window.inner_size().into(),
|
||||||
image_usage: ImageUsage {
|
image_usage: ImageUsage::COLOR_ATTACHMENT,
|
||||||
color_attachment: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
},
|
|
||||||
composite_alpha: surface_capabilities
|
composite_alpha: surface_capabilities
|
||||||
.supported_composite_alpha
|
.supported_composite_alpha
|
||||||
.iter()
|
.into_iter()
|
||||||
.next()
|
.next()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -240,10 +239,7 @@ fn main() {
|
|||||||
];
|
];
|
||||||
let vertex_buffer = CpuAccessibleBuffer::from_iter(
|
let vertex_buffer = CpuAccessibleBuffer::from_iter(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::VERTEX_BUFFER,
|
||||||
vertex_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
vertices,
|
vertices,
|
||||||
)
|
)
|
||||||
|
@ -24,7 +24,7 @@ use vulkano::{
|
|||||||
},
|
},
|
||||||
device::{
|
device::{
|
||||||
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, Features,
|
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, Features,
|
||||||
QueueCreateInfo,
|
QueueCreateInfo, QueueFlags,
|
||||||
},
|
},
|
||||||
format::Format,
|
format::Format,
|
||||||
image::{
|
image::{
|
||||||
@ -94,7 +94,8 @@ fn main() {
|
|||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.position(|(i, q)| {
|
.position(|(i, q)| {
|
||||||
q.queue_flags.graphics && p.surface_support(i as u32, &surface).unwrap_or(false)
|
q.queue_flags.intersects(QueueFlags::GRAPHICS)
|
||||||
|
&& p.surface_support(i as u32, &surface).unwrap_or(false)
|
||||||
})
|
})
|
||||||
.map(|i| (p, i as u32))
|
.map(|i| (p, i as u32))
|
||||||
})
|
})
|
||||||
@ -156,13 +157,10 @@ fn main() {
|
|||||||
min_image_count: surface_capabilities.min_image_count,
|
min_image_count: surface_capabilities.min_image_count,
|
||||||
image_format,
|
image_format,
|
||||||
image_extent: window.inner_size().into(),
|
image_extent: window.inner_size().into(),
|
||||||
image_usage: ImageUsage {
|
image_usage: ImageUsage::COLOR_ATTACHMENT,
|
||||||
color_attachment: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
},
|
|
||||||
composite_alpha: surface_capabilities
|
composite_alpha: surface_capabilities
|
||||||
.supported_composite_alpha
|
.supported_composite_alpha
|
||||||
.iter()
|
.into_iter()
|
||||||
.next()
|
.next()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -246,10 +244,7 @@ fn main() {
|
|||||||
];
|
];
|
||||||
let vertex_buffer = CpuAccessibleBuffer::<[Vertex]>::from_iter(
|
let vertex_buffer = CpuAccessibleBuffer::<[Vertex]>::from_iter(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::VERTEX_BUFFER,
|
||||||
vertex_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
vertices,
|
vertices,
|
||||||
)
|
)
|
||||||
|
@ -21,6 +21,7 @@ use vulkano::{
|
|||||||
},
|
},
|
||||||
device::{
|
device::{
|
||||||
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
||||||
|
QueueFlags,
|
||||||
},
|
},
|
||||||
instance::{Instance, InstanceCreateInfo},
|
instance::{Instance, InstanceCreateInfo},
|
||||||
memory::allocator::StandardMemoryAllocator,
|
memory::allocator::StandardMemoryAllocator,
|
||||||
@ -52,7 +53,7 @@ fn main() {
|
|||||||
.filter_map(|p| {
|
.filter_map(|p| {
|
||||||
p.queue_family_properties()
|
p.queue_family_properties()
|
||||||
.iter()
|
.iter()
|
||||||
.position(|q| q.queue_flags.compute)
|
.position(|q| q.queue_flags.intersects(QueueFlags::COMPUTE))
|
||||||
.map(|i| (p, i as u32))
|
.map(|i| (p, i as u32))
|
||||||
})
|
})
|
||||||
.min_by_key(|(p, _)| match p.properties().device_type {
|
.min_by_key(|(p, _)| match p.properties().device_type {
|
||||||
@ -127,12 +128,7 @@ fn main() {
|
|||||||
let data_iter = (0..65536u32).map(|n| if n < 65536 / 2 { n } else { 0 });
|
let data_iter = (0..65536u32).map(|n| if n < 65536 / 2 { n } else { 0 });
|
||||||
CpuAccessibleBuffer::from_iter(
|
CpuAccessibleBuffer::from_iter(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::STORAGE_BUFFER | BufferUsage::TRANSFER_SRC | BufferUsage::TRANSFER_DST,
|
||||||
storage_buffer: true,
|
|
||||||
transfer_src: true,
|
|
||||||
transfer_dst: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
data_iter,
|
data_iter,
|
||||||
)
|
)
|
||||||
|
@ -21,6 +21,7 @@ use vulkano::{
|
|||||||
},
|
},
|
||||||
device::{
|
device::{
|
||||||
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
||||||
|
QueueFlags,
|
||||||
},
|
},
|
||||||
instance::{Instance, InstanceCreateInfo},
|
instance::{Instance, InstanceCreateInfo},
|
||||||
memory::allocator::StandardMemoryAllocator,
|
memory::allocator::StandardMemoryAllocator,
|
||||||
@ -52,7 +53,7 @@ fn main() {
|
|||||||
.filter_map(|p| {
|
.filter_map(|p| {
|
||||||
p.queue_family_properties()
|
p.queue_family_properties()
|
||||||
.iter()
|
.iter()
|
||||||
.position(|q| q.queue_flags.compute)
|
.position(|q| q.queue_flags.intersects(QueueFlags::COMPUTE))
|
||||||
.map(|i| (p, i as u32))
|
.map(|i| (p, i as u32))
|
||||||
})
|
})
|
||||||
.min_by_key(|(p, _)| match p.properties().device_type {
|
.min_by_key(|(p, _)| match p.properties().device_type {
|
||||||
@ -134,10 +135,7 @@ fn main() {
|
|||||||
let data_iter = 0..65536u32;
|
let data_iter = 0..65536u32;
|
||||||
CpuAccessibleBuffer::from_iter(
|
CpuAccessibleBuffer::from_iter(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::STORAGE_BUFFER,
|
||||||
storage_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
data_iter,
|
data_iter,
|
||||||
)
|
)
|
||||||
|
@ -38,7 +38,7 @@ use vulkano::{
|
|||||||
},
|
},
|
||||||
device::{
|
device::{
|
||||||
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, Queue,
|
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, Queue,
|
||||||
QueueCreateInfo,
|
QueueCreateInfo, QueueFlags,
|
||||||
},
|
},
|
||||||
instance::{Instance, InstanceCreateInfo},
|
instance::{Instance, InstanceCreateInfo},
|
||||||
memory::allocator::StandardMemoryAllocator,
|
memory::allocator::StandardMemoryAllocator,
|
||||||
@ -70,7 +70,7 @@ fn main() {
|
|||||||
.filter_map(|p| {
|
.filter_map(|p| {
|
||||||
p.queue_family_properties()
|
p.queue_family_properties()
|
||||||
.iter()
|
.iter()
|
||||||
.position(|q| q.queue_flags.compute)
|
.position(|q| q.queue_flags.intersects(QueueFlags::COMPUTE))
|
||||||
.map(|i| (p, i as u32))
|
.map(|i| (p, i as u32))
|
||||||
})
|
})
|
||||||
.min_by_key(|(p, _)| match p.properties().device_type {
|
.min_by_key(|(p, _)| match p.properties().device_type {
|
||||||
@ -248,10 +248,7 @@ fn main() {
|
|||||||
let data_iter = 0..65536u32;
|
let data_iter = 0..65536u32;
|
||||||
CpuAccessibleBuffer::from_iter(
|
CpuAccessibleBuffer::from_iter(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::STORAGE_BUFFER,
|
||||||
storage_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
data_iter,
|
data_iter,
|
||||||
)
|
)
|
||||||
|
@ -26,6 +26,7 @@ use vulkano::{
|
|||||||
},
|
},
|
||||||
device::{
|
device::{
|
||||||
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
||||||
|
QueueFlags,
|
||||||
},
|
},
|
||||||
image::{view::ImageView, ImageUsage},
|
image::{view::ImageView, ImageUsage},
|
||||||
impl_vertex,
|
impl_vertex,
|
||||||
@ -93,7 +94,8 @@ fn main() {
|
|||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.position(|(i, q)| {
|
.position(|(i, q)| {
|
||||||
q.queue_flags.graphics && p.surface_support(i as u32, &surface).unwrap_or(false)
|
q.queue_flags.intersects(QueueFlags::GRAPHICS)
|
||||||
|
&& p.surface_support(i as u32, &surface).unwrap_or(false)
|
||||||
})
|
})
|
||||||
.map(|i| (p, i as u32))
|
.map(|i| (p, i as u32))
|
||||||
})
|
})
|
||||||
@ -147,13 +149,10 @@ fn main() {
|
|||||||
min_image_count: surface_capabilities.min_image_count,
|
min_image_count: surface_capabilities.min_image_count,
|
||||||
image_format,
|
image_format,
|
||||||
image_extent: [WINDOW_WIDTH as u32, WINDOW_HEIGHT as u32],
|
image_extent: [WINDOW_WIDTH as u32, WINDOW_HEIGHT as u32],
|
||||||
image_usage: ImageUsage {
|
image_usage: ImageUsage::COLOR_ATTACHMENT,
|
||||||
color_attachment: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
},
|
|
||||||
composite_alpha: surface_capabilities
|
composite_alpha: surface_capabilities
|
||||||
.supported_composite_alpha
|
.supported_composite_alpha
|
||||||
.iter()
|
.into_iter()
|
||||||
.next()
|
.next()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
present_mode: PresentMode::Fifo,
|
present_mode: PresentMode::Fifo,
|
||||||
@ -345,10 +344,7 @@ fn main() {
|
|||||||
// Create a CPU accessible buffer initialized with the vertex data.
|
// Create a CPU accessible buffer initialized with the vertex data.
|
||||||
let temporary_accessible_buffer = CpuAccessibleBuffer::from_iter(
|
let temporary_accessible_buffer = CpuAccessibleBuffer::from_iter(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::TRANSFER_SRC, // Specify this buffer will be used as a transfer source.
|
||||||
transfer_src: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
}, // Specify this buffer will be used as a transfer source.
|
|
||||||
false,
|
false,
|
||||||
vertices,
|
vertices,
|
||||||
)
|
)
|
||||||
@ -358,14 +354,7 @@ fn main() {
|
|||||||
let device_local_buffer = DeviceLocalBuffer::<[Vertex]>::array(
|
let device_local_buffer = DeviceLocalBuffer::<[Vertex]>::array(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
PARTICLE_COUNT as vulkano::DeviceSize,
|
PARTICLE_COUNT as vulkano::DeviceSize,
|
||||||
BufferUsage {
|
BufferUsage::STORAGE_BUFFER | BufferUsage::TRANSFER_DST | BufferUsage::VERTEX_BUFFER, // Specify use as a storage buffer, vertex buffer, and transfer destination.
|
||||||
storage_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
} | BufferUsage {
|
|
||||||
transfer_dst: true,
|
|
||||||
vertex_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
}, // Specify use as a storage buffer, vertex buffer, and transfer destination.
|
|
||||||
device.active_queue_family_indices().iter().copied(),
|
device.active_queue_family_indices().iter().copied(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -19,6 +19,7 @@ use vulkano::{
|
|||||||
},
|
},
|
||||||
device::{
|
device::{
|
||||||
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
||||||
|
QueueFlags,
|
||||||
},
|
},
|
||||||
instance::{Instance, InstanceCreateInfo},
|
instance::{Instance, InstanceCreateInfo},
|
||||||
memory::allocator::StandardMemoryAllocator,
|
memory::allocator::StandardMemoryAllocator,
|
||||||
@ -50,7 +51,7 @@ fn main() {
|
|||||||
.filter_map(|p| {
|
.filter_map(|p| {
|
||||||
p.queue_family_properties()
|
p.queue_family_properties()
|
||||||
.iter()
|
.iter()
|
||||||
.position(|q| q.queue_flags.compute)
|
.position(|q| q.queue_flags.intersects(QueueFlags::COMPUTE))
|
||||||
.map(|i| (p, i as u32))
|
.map(|i| (p, i as u32))
|
||||||
})
|
})
|
||||||
.min_by_key(|(p, _)| match p.properties().device_type {
|
.min_by_key(|(p, _)| match p.properties().device_type {
|
||||||
@ -135,10 +136,7 @@ fn main() {
|
|||||||
let data_iter = 0..65536u32;
|
let data_iter = 0..65536u32;
|
||||||
CpuAccessibleBuffer::from_iter(
|
CpuAccessibleBuffer::from_iter(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::STORAGE_BUFFER,
|
||||||
storage_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
data_iter,
|
data_iter,
|
||||||
)
|
)
|
||||||
|
@ -21,7 +21,7 @@ use vulkano::{
|
|||||||
},
|
},
|
||||||
device::{
|
device::{
|
||||||
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, DeviceOwned,
|
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, DeviceOwned,
|
||||||
QueueCreateInfo,
|
QueueCreateInfo, QueueFlags,
|
||||||
},
|
},
|
||||||
format::Format,
|
format::Format,
|
||||||
image::{view::ImageView, AttachmentImage, ImageAccess, ImageUsage, SwapchainImage},
|
image::{view::ImageView, AttachmentImage, ImageAccess, ImageUsage, SwapchainImage},
|
||||||
@ -87,7 +87,8 @@ fn main() {
|
|||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.position(|(i, q)| {
|
.position(|(i, q)| {
|
||||||
q.queue_flags.graphics && p.surface_support(i as u32, &surface).unwrap_or(false)
|
q.queue_flags.intersects(QueueFlags::GRAPHICS)
|
||||||
|
&& p.surface_support(i as u32, &surface).unwrap_or(false)
|
||||||
})
|
})
|
||||||
.map(|i| (p, i as u32))
|
.map(|i| (p, i as u32))
|
||||||
})
|
})
|
||||||
@ -143,13 +144,10 @@ fn main() {
|
|||||||
min_image_count: surface_capabilities.min_image_count,
|
min_image_count: surface_capabilities.min_image_count,
|
||||||
image_format,
|
image_format,
|
||||||
image_extent: window.inner_size().into(),
|
image_extent: window.inner_size().into(),
|
||||||
image_usage: ImageUsage {
|
image_usage: ImageUsage::COLOR_ATTACHMENT,
|
||||||
color_attachment: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
},
|
|
||||||
composite_alpha: surface_capabilities
|
composite_alpha: surface_capabilities
|
||||||
.supported_composite_alpha
|
.supported_composite_alpha
|
||||||
.iter()
|
.into_iter()
|
||||||
.next()
|
.next()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -162,30 +160,21 @@ fn main() {
|
|||||||
|
|
||||||
let vertex_buffer = CpuAccessibleBuffer::from_iter(
|
let vertex_buffer = CpuAccessibleBuffer::from_iter(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::VERTEX_BUFFER,
|
||||||
vertex_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
VERTICES,
|
VERTICES,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let normals_buffer = CpuAccessibleBuffer::from_iter(
|
let normals_buffer = CpuAccessibleBuffer::from_iter(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::VERTEX_BUFFER,
|
||||||
vertex_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
NORMALS,
|
NORMALS,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let index_buffer = CpuAccessibleBuffer::from_iter(
|
let index_buffer = CpuAccessibleBuffer::from_iter(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::INDEX_BUFFER,
|
||||||
index_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
INDICES,
|
INDICES,
|
||||||
)
|
)
|
||||||
@ -193,10 +182,7 @@ fn main() {
|
|||||||
|
|
||||||
let uniform_buffer = CpuBufferPool::<vs::ty::Data>::new(
|
let uniform_buffer = CpuBufferPool::<vs::ty::Data>::new(
|
||||||
memory_allocator.clone(),
|
memory_allocator.clone(),
|
||||||
BufferUsage {
|
BufferUsage::UNIFORM_BUFFER,
|
||||||
uniform_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
MemoryUsage::Upload,
|
MemoryUsage::Upload,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ use vulkano::{
|
|||||||
},
|
},
|
||||||
device::{
|
device::{
|
||||||
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, Features,
|
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, Features,
|
||||||
QueueCreateInfo,
|
QueueCreateInfo, QueueFlags,
|
||||||
},
|
},
|
||||||
image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage},
|
image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage},
|
||||||
impl_vertex,
|
impl_vertex,
|
||||||
@ -192,7 +192,8 @@ fn main() {
|
|||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.position(|(i, q)| {
|
.position(|(i, q)| {
|
||||||
q.queue_flags.graphics && p.surface_support(i as u32, &surface).unwrap_or(false)
|
q.queue_flags.intersects(QueueFlags::GRAPHICS)
|
||||||
|
&& p.surface_support(i as u32, &surface).unwrap_or(false)
|
||||||
})
|
})
|
||||||
.map(|i| (p, i as u32))
|
.map(|i| (p, i as u32))
|
||||||
})
|
})
|
||||||
@ -248,13 +249,10 @@ fn main() {
|
|||||||
min_image_count: surface_capabilities.min_image_count,
|
min_image_count: surface_capabilities.min_image_count,
|
||||||
image_format,
|
image_format,
|
||||||
image_extent: window.inner_size().into(),
|
image_extent: window.inner_size().into(),
|
||||||
image_usage: ImageUsage {
|
image_usage: ImageUsage::COLOR_ATTACHMENT,
|
||||||
color_attachment: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
},
|
|
||||||
composite_alpha: surface_capabilities
|
composite_alpha: surface_capabilities
|
||||||
.supported_composite_alpha
|
.supported_composite_alpha
|
||||||
.iter()
|
.into_iter()
|
||||||
.next()
|
.next()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -303,10 +301,7 @@ fn main() {
|
|||||||
];
|
];
|
||||||
let vertex_buffer = CpuAccessibleBuffer::from_iter(
|
let vertex_buffer = CpuAccessibleBuffer::from_iter(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::VERTEX_BUFFER,
|
||||||
vertex_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
vertices,
|
vertices,
|
||||||
)
|
)
|
||||||
|
@ -20,6 +20,7 @@ use vulkano::{
|
|||||||
},
|
},
|
||||||
device::{
|
device::{
|
||||||
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
||||||
|
QueueFlags,
|
||||||
},
|
},
|
||||||
format::Format,
|
format::Format,
|
||||||
image::{
|
image::{
|
||||||
@ -91,7 +92,8 @@ fn main() {
|
|||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.position(|(i, q)| {
|
.position(|(i, q)| {
|
||||||
q.queue_flags.graphics && p.surface_support(i as u32, &surface).unwrap_or(false)
|
q.queue_flags.intersects(QueueFlags::GRAPHICS)
|
||||||
|
&& p.surface_support(i as u32, &surface).unwrap_or(false)
|
||||||
})
|
})
|
||||||
.map(|i| (p, i as u32))
|
.map(|i| (p, i as u32))
|
||||||
})
|
})
|
||||||
@ -146,13 +148,10 @@ fn main() {
|
|||||||
min_image_count: surface_capabilities.min_image_count,
|
min_image_count: surface_capabilities.min_image_count,
|
||||||
image_format,
|
image_format,
|
||||||
image_extent: window.inner_size().into(),
|
image_extent: window.inner_size().into(),
|
||||||
image_usage: ImageUsage {
|
image_usage: ImageUsage::COLOR_ATTACHMENT,
|
||||||
color_attachment: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
},
|
|
||||||
composite_alpha: surface_capabilities
|
composite_alpha: surface_capabilities
|
||||||
.supported_composite_alpha
|
.supported_composite_alpha
|
||||||
.iter()
|
.into_iter()
|
||||||
.next()
|
.next()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -186,10 +185,7 @@ fn main() {
|
|||||||
];
|
];
|
||||||
let vertex_buffer = CpuAccessibleBuffer::<[Vertex]>::from_iter(
|
let vertex_buffer = CpuAccessibleBuffer::<[Vertex]>::from_iter(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::VERTEX_BUFFER,
|
||||||
vertex_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
vertices,
|
vertices,
|
||||||
)
|
)
|
||||||
|
@ -31,7 +31,7 @@ use vulkano::{
|
|||||||
},
|
},
|
||||||
device::{
|
device::{
|
||||||
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, Features,
|
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, Features,
|
||||||
QueueCreateInfo,
|
QueueCreateInfo, QueueFlags,
|
||||||
},
|
},
|
||||||
image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage},
|
image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage},
|
||||||
impl_vertex,
|
impl_vertex,
|
||||||
@ -142,7 +142,8 @@ fn main() {
|
|||||||
// We select a queue family that supports graphics operations. When drawing to
|
// We select a queue family that supports graphics operations. When drawing to
|
||||||
// a window surface, as we do in this example, we also need to check that queues
|
// a window surface, as we do in this example, we also need to check that queues
|
||||||
// in this queue family are capable of presenting images to the surface.
|
// in this queue family are capable of presenting images to the surface.
|
||||||
q.queue_flags.graphics && p.surface_support(i as u32, &surface).unwrap_or(false)
|
q.queue_flags.intersects(QueueFlags::GRAPHICS)
|
||||||
|
&& p.surface_support(i as u32, &surface).unwrap_or(false)
|
||||||
})
|
})
|
||||||
// The code here searches for the first queue family that is suitable. If none is
|
// The code here searches for the first queue family that is suitable. If none is
|
||||||
// found, `None` is returned to `filter_map`, which disqualifies this physical
|
// found, `None` is returned to `filter_map`, which disqualifies this physical
|
||||||
@ -261,16 +262,13 @@ fn main() {
|
|||||||
// use that.
|
// use that.
|
||||||
image_extent: window.inner_size().into(),
|
image_extent: window.inner_size().into(),
|
||||||
|
|
||||||
image_usage: ImageUsage {
|
image_usage: ImageUsage::COLOR_ATTACHMENT,
|
||||||
color_attachment: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
},
|
|
||||||
|
|
||||||
// The alpha mode indicates how the alpha value of the final image will behave. For
|
// The alpha mode indicates how the alpha value of the final image will behave. For
|
||||||
// example, you can choose whether the window will be opaque or transparent.
|
// example, you can choose whether the window will be opaque or transparent.
|
||||||
composite_alpha: surface_capabilities
|
composite_alpha: surface_capabilities
|
||||||
.supported_composite_alpha
|
.supported_composite_alpha
|
||||||
.iter()
|
.into_iter()
|
||||||
.next()
|
.next()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
|
|
||||||
@ -305,10 +303,7 @@ fn main() {
|
|||||||
];
|
];
|
||||||
let vertex_buffer = CpuAccessibleBuffer::from_iter(
|
let vertex_buffer = CpuAccessibleBuffer::from_iter(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::VERTEX_BUFFER,
|
||||||
vertex_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
vertices,
|
vertices,
|
||||||
)
|
)
|
||||||
|
@ -26,6 +26,7 @@ use vulkano::{
|
|||||||
},
|
},
|
||||||
device::{
|
device::{
|
||||||
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
||||||
|
QueueFlags,
|
||||||
},
|
},
|
||||||
image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage},
|
image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage},
|
||||||
impl_vertex,
|
impl_vertex,
|
||||||
@ -131,7 +132,8 @@ fn main() {
|
|||||||
// We select a queue family that supports graphics operations. When drawing to
|
// We select a queue family that supports graphics operations. When drawing to
|
||||||
// a window surface, as we do in this example, we also need to check that queues
|
// a window surface, as we do in this example, we also need to check that queues
|
||||||
// in this queue family are capable of presenting images to the surface.
|
// in this queue family are capable of presenting images to the surface.
|
||||||
q.queue_flags.graphics && p.surface_support(i as u32, &surface).unwrap_or(false)
|
q.queue_flags.intersects(QueueFlags::GRAPHICS)
|
||||||
|
&& p.surface_support(i as u32, &surface).unwrap_or(false)
|
||||||
})
|
})
|
||||||
// The code here searches for the first queue family that is suitable. If none is
|
// The code here searches for the first queue family that is suitable. If none is
|
||||||
// found, `None` is returned to `filter_map`, which disqualifies this physical
|
// found, `None` is returned to `filter_map`, which disqualifies this physical
|
||||||
@ -241,16 +243,13 @@ fn main() {
|
|||||||
// use that.
|
// use that.
|
||||||
image_extent: window.inner_size().into(),
|
image_extent: window.inner_size().into(),
|
||||||
|
|
||||||
image_usage: ImageUsage {
|
image_usage: ImageUsage::COLOR_ATTACHMENT,
|
||||||
color_attachment: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
},
|
|
||||||
|
|
||||||
// The alpha mode indicates how the alpha value of the final image will behave. For
|
// The alpha mode indicates how the alpha value of the final image will behave. For
|
||||||
// example, you can choose whether the window will be opaque or transparent.
|
// example, you can choose whether the window will be opaque or transparent.
|
||||||
composite_alpha: surface_capabilities
|
composite_alpha: surface_capabilities
|
||||||
.supported_composite_alpha
|
.supported_composite_alpha
|
||||||
.iter()
|
.into_iter()
|
||||||
.next()
|
.next()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
|
|
||||||
@ -285,10 +284,7 @@ fn main() {
|
|||||||
];
|
];
|
||||||
let vertex_buffer = CpuAccessibleBuffer::from_iter(
|
let vertex_buffer = CpuAccessibleBuffer::from_iter(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::VERTEX_BUFFER,
|
||||||
vertex_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
vertices,
|
vertices,
|
||||||
)
|
)
|
||||||
|
@ -165,38 +165,47 @@ fn write_descriptor_requirements(
|
|||||||
})
|
})
|
||||||
};
|
};
|
||||||
let stages = {
|
let stages = {
|
||||||
let ShaderStages {
|
let stages_items = [
|
||||||
vertex,
|
stages.intersects(ShaderStages::VERTEX).then(|| quote! {
|
||||||
tessellation_control,
|
::vulkano::shader::ShaderStages::VERTEX
|
||||||
tessellation_evaluation,
|
}),
|
||||||
geometry,
|
stages.intersects(ShaderStages::TESSELLATION_CONTROL).then(|| quote! {
|
||||||
fragment,
|
::vulkano::shader::ShaderStages::TESSELLATION_CONTROL
|
||||||
compute,
|
}),
|
||||||
raygen,
|
stages.intersects(ShaderStages::TESSELLATION_EVALUATION).then(|| quote! {
|
||||||
any_hit,
|
::vulkano::shader::ShaderStages::TESSELLATION_EVALUATION
|
||||||
closest_hit,
|
}),
|
||||||
miss,
|
stages.intersects(ShaderStages::GEOMETRY).then(|| quote! {
|
||||||
intersection,
|
::vulkano::shader::ShaderStages::GEOMETRY
|
||||||
callable,
|
}),
|
||||||
_ne: _,
|
stages.intersects(ShaderStages::FRAGMENT).then(|| quote! {
|
||||||
} = stages;
|
::vulkano::shader::ShaderStages::FRAGMENT
|
||||||
|
}),
|
||||||
|
stages.intersects(ShaderStages::COMPUTE).then(|| quote! {
|
||||||
|
::vulkano::shader::ShaderStages::COMPUTE
|
||||||
|
}),
|
||||||
|
stages.intersects(ShaderStages::RAYGEN).then(|| quote! {
|
||||||
|
::vulkano::shader::ShaderStages::RAYGEN
|
||||||
|
}),
|
||||||
|
stages.intersects(ShaderStages::ANY_HIT).then(|| quote! {
|
||||||
|
::vulkano::shader::ShaderStages::ANY_HIT
|
||||||
|
}),
|
||||||
|
stages.intersects(ShaderStages::CLOSEST_HIT).then(|| quote! {
|
||||||
|
::vulkano::shader::ShaderStages::CLOSEST_HIT
|
||||||
|
}),
|
||||||
|
stages.intersects(ShaderStages::MISS).then(|| quote! {
|
||||||
|
::vulkano::shader::ShaderStages::MISS
|
||||||
|
}),
|
||||||
|
stages.intersects(ShaderStages::INTERSECTION).then(|| quote! {
|
||||||
|
::vulkano::shader::ShaderStages::INTERSECTION
|
||||||
|
}),
|
||||||
|
stages.intersects(ShaderStages::CALLABLE).then(|| quote! {
|
||||||
|
::vulkano::shader::ShaderStages::CALLABLE
|
||||||
|
}),
|
||||||
|
].into_iter().flatten();
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
::vulkano::shader::ShaderStages {
|
#(#stages_items)|*
|
||||||
vertex: #vertex,
|
|
||||||
tessellation_control: #tessellation_control,
|
|
||||||
tessellation_evaluation: #tessellation_evaluation,
|
|
||||||
geometry: #geometry,
|
|
||||||
fragment: #fragment,
|
|
||||||
compute: #compute,
|
|
||||||
raygen: #raygen,
|
|
||||||
any_hit: #any_hit,
|
|
||||||
closest_hit: #closest_hit,
|
|
||||||
miss: #miss,
|
|
||||||
intersection: #intersection,
|
|
||||||
callable: #callable,
|
|
||||||
..::vulkano::shader::ShaderStages::empty()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let storage_image_atomic = storage_image_atomic.iter();
|
let storage_image_atomic = storage_image_atomic.iter();
|
||||||
@ -243,38 +252,77 @@ fn write_push_constant_requirements(
|
|||||||
stages,
|
stages,
|
||||||
}) => {
|
}) => {
|
||||||
let stages = {
|
let stages = {
|
||||||
let ShaderStages {
|
let stages_items = [
|
||||||
vertex,
|
stages.intersects(ShaderStages::VERTEX).then(|| {
|
||||||
tessellation_control,
|
quote! {
|
||||||
tessellation_evaluation,
|
::vulkano::shader::ShaderStages::VERTEX
|
||||||
geometry,
|
}
|
||||||
fragment,
|
}),
|
||||||
compute,
|
stages
|
||||||
raygen,
|
.intersects(ShaderStages::TESSELLATION_CONTROL)
|
||||||
any_hit,
|
.then(|| {
|
||||||
closest_hit,
|
quote! {
|
||||||
miss,
|
::vulkano::shader::ShaderStages::TESSELLATION_CONTROL
|
||||||
intersection,
|
}
|
||||||
callable,
|
}),
|
||||||
_ne: _,
|
stages
|
||||||
} = stages;
|
.intersects(ShaderStages::TESSELLATION_EVALUATION)
|
||||||
|
.then(|| {
|
||||||
|
quote! {
|
||||||
|
::vulkano::shader::ShaderStages::TESSELLATION_EVALUATION
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
stages.intersects(ShaderStages::GEOMETRY).then(|| {
|
||||||
|
quote! {
|
||||||
|
::vulkano::shader::ShaderStages::GEOMETRY
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
stages.intersects(ShaderStages::FRAGMENT).then(|| {
|
||||||
|
quote! {
|
||||||
|
::vulkano::shader::ShaderStages::FRAGMENT
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
stages.intersects(ShaderStages::COMPUTE).then(|| {
|
||||||
|
quote! {
|
||||||
|
::vulkano::shader::ShaderStages::COMPUTE
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
stages.intersects(ShaderStages::RAYGEN).then(|| {
|
||||||
|
quote! {
|
||||||
|
::vulkano::shader::ShaderStages::RAYGEN
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
stages.intersects(ShaderStages::ANY_HIT).then(|| {
|
||||||
|
quote! {
|
||||||
|
::vulkano::shader::ShaderStages::ANY_HIT
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
stages.intersects(ShaderStages::CLOSEST_HIT).then(|| {
|
||||||
|
quote! {
|
||||||
|
::vulkano::shader::ShaderStages::CLOSEST_HIT
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
stages.intersects(ShaderStages::MISS).then(|| {
|
||||||
|
quote! {
|
||||||
|
::vulkano::shader::ShaderStages::MISS
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
stages.intersects(ShaderStages::INTERSECTION).then(|| {
|
||||||
|
quote! {
|
||||||
|
::vulkano::shader::ShaderStages::INTERSECTION
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
stages.intersects(ShaderStages::CALLABLE).then(|| {
|
||||||
|
quote! {
|
||||||
|
::vulkano::shader::ShaderStages::CALLABLE
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
]
|
||||||
|
.into_iter()
|
||||||
|
.flatten();
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
::vulkano::shader::ShaderStages {
|
#(#stages_items)|*
|
||||||
vertex: #vertex,
|
|
||||||
tessellation_control: #tessellation_control,
|
|
||||||
tessellation_evaluation: #tessellation_evaluation,
|
|
||||||
geometry: #geometry,
|
|
||||||
fragment: #fragment,
|
|
||||||
compute: #compute,
|
|
||||||
raygen: #raygen,
|
|
||||||
any_hit: #any_hit,
|
|
||||||
closest_hit: #closest_hit,
|
|
||||||
miss: #miss,
|
|
||||||
intersection: #intersection,
|
|
||||||
callable: #callable,
|
|
||||||
..::vulkano::shader::ShaderStages::empty()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ use std::sync::Arc;
|
|||||||
use vulkano::{
|
use vulkano::{
|
||||||
device::{
|
device::{
|
||||||
physical::{PhysicalDevice, PhysicalDeviceType},
|
physical::{PhysicalDevice, PhysicalDeviceType},
|
||||||
Device, DeviceCreateInfo, DeviceExtensions, Features, Queue, QueueCreateInfo,
|
Device, DeviceCreateInfo, DeviceExtensions, Features, Queue, QueueCreateInfo, QueueFlags,
|
||||||
},
|
},
|
||||||
instance::{
|
instance::{
|
||||||
debug::{DebugUtilsMessenger, DebugUtilsMessengerCreateInfo},
|
debug::{DebugUtilsMessenger, DebugUtilsMessengerCreateInfo},
|
||||||
@ -199,7 +199,7 @@ impl VulkanoContext {
|
|||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, q)| (i as u32, q))
|
.map(|(i, q)| (i as u32, q))
|
||||||
.find(|(_i, q)| q.queue_flags.graphics)
|
.find(|(_i, q)| q.queue_flags.intersects(QueueFlags::GRAPHICS))
|
||||||
.map(|(i, _)| i)
|
.map(|(i, _)| i)
|
||||||
.expect("Could not find a queue that supports graphics");
|
.expect("Could not find a queue that supports graphics");
|
||||||
// Try finding a separate queue for compute
|
// Try finding a separate queue for compute
|
||||||
@ -208,7 +208,9 @@ impl VulkanoContext {
|
|||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, q)| (i as u32, q))
|
.map(|(i, q)| (i as u32, q))
|
||||||
.find(|(i, q)| q.queue_flags.compute && *i != queue_family_graphics)
|
.find(|(i, q)| {
|
||||||
|
q.queue_flags.intersects(QueueFlags::COMPUTE) && *i != queue_family_graphics
|
||||||
|
})
|
||||||
.map(|(i, _)| i);
|
.map(|(i, _)| i);
|
||||||
let is_separate_compute_queue = queue_family_compute.is_some();
|
let is_separate_compute_queue = queue_family_compute.is_some();
|
||||||
|
|
||||||
|
@ -124,13 +124,10 @@ impl VulkanoWindowRenderer {
|
|||||||
min_image_count: surface_capabilities.min_image_count,
|
min_image_count: surface_capabilities.min_image_count,
|
||||||
image_format,
|
image_format,
|
||||||
image_extent,
|
image_extent,
|
||||||
image_usage: ImageUsage {
|
image_usage: ImageUsage::COLOR_ATTACHMENT,
|
||||||
color_attachment: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
},
|
|
||||||
composite_alpha: surface_capabilities
|
composite_alpha: surface_capabilities
|
||||||
.supported_composite_alpha
|
.supported_composite_alpha
|
||||||
.iter()
|
.into_iter()
|
||||||
.next()
|
.next()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -371,7 +368,7 @@ impl VulkanoWindowRenderer {
|
|||||||
.collect::<Vec<usize>>();
|
.collect::<Vec<usize>>();
|
||||||
for i in resizable_views {
|
for i in resizable_views {
|
||||||
let format = self.get_additional_image_view(i).format().unwrap();
|
let format = self.get_additional_image_view(i).format().unwrap();
|
||||||
let usage = *self.get_additional_image_view(i).usage();
|
let usage = self.get_additional_image_view(i).usage();
|
||||||
self.remove_additional_image_view(i);
|
self.remove_additional_image_view(i);
|
||||||
self.add_additional_image_view(i, format, usage);
|
self.add_additional_image_view(i, format, usage);
|
||||||
}
|
}
|
||||||
|
@ -63,78 +63,30 @@ fn formats_output(members: &[FormatMember]) -> TokenStream {
|
|||||||
let enum_items = members.iter().map(|FormatMember { name, ffi_name, .. }| {
|
let enum_items = members.iter().map(|FormatMember { name, ffi_name, .. }| {
|
||||||
quote! { #name = ash::vk::Format::#ffi_name.as_raw(), }
|
quote! { #name = ash::vk::Format::#ffi_name.as_raw(), }
|
||||||
});
|
});
|
||||||
let aspects_color_items = members.iter().filter_map(
|
let aspects_items = members.iter().map(
|
||||||
|FormatMember {
|
|
||||||
name, aspect_color, ..
|
|
||||||
}| {
|
|
||||||
if !aspect_color {
|
|
||||||
// Negated to reduce the length of the list
|
|
||||||
Some(name)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
let aspects_depth_items = members.iter().filter_map(
|
|
||||||
|FormatMember {
|
|
||||||
name, aspect_depth, ..
|
|
||||||
}| {
|
|
||||||
if *aspect_depth {
|
|
||||||
Some(name)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
let aspects_stencil_items = members.iter().filter_map(
|
|
||||||
|FormatMember {
|
|FormatMember {
|
||||||
name,
|
name,
|
||||||
|
aspect_color,
|
||||||
|
aspect_depth,
|
||||||
aspect_stencil,
|
aspect_stencil,
|
||||||
..
|
|
||||||
}| {
|
|
||||||
if *aspect_stencil {
|
|
||||||
Some(name)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
let aspects_plane0_items = members.iter().filter_map(
|
|
||||||
|FormatMember {
|
|
||||||
name,
|
|
||||||
aspect_plane0,
|
aspect_plane0,
|
||||||
..
|
|
||||||
}| {
|
|
||||||
if *aspect_plane0 {
|
|
||||||
Some(name)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
let aspects_plane1_items = members.iter().filter_map(
|
|
||||||
|FormatMember {
|
|
||||||
name,
|
|
||||||
aspect_plane1,
|
aspect_plane1,
|
||||||
..
|
|
||||||
}| {
|
|
||||||
if *aspect_plane1 {
|
|
||||||
Some(name)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
let aspects_plane2_items = members.iter().filter_map(
|
|
||||||
|FormatMember {
|
|
||||||
name,
|
|
||||||
aspect_plane2,
|
aspect_plane2,
|
||||||
..
|
..
|
||||||
}| {
|
}| {
|
||||||
if *aspect_plane2 {
|
let aspect_items = [
|
||||||
Some(name)
|
aspect_color.then(|| quote! { crate::image::ImageAspects::COLOR }),
|
||||||
} else {
|
aspect_depth.then(|| quote! { crate::image::ImageAspects::DEPTH }),
|
||||||
None
|
aspect_stencil.then(|| quote! { crate::image::ImageAspects::STENCIL }),
|
||||||
|
aspect_plane0.then(|| quote! { crate::image::ImageAspects::PLANE_0 }),
|
||||||
|
aspect_plane1.then(|| quote! { crate::image::ImageAspects::PLANE_1 }),
|
||||||
|
aspect_plane2.then(|| quote! { crate::image::ImageAspects::PLANE_2 }),
|
||||||
|
]
|
||||||
|
.into_iter()
|
||||||
|
.flatten();
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
Self::#name => #(#aspect_items)|*,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -381,15 +333,9 @@ fn formats_output(members: &[FormatMember]) -> TokenStream {
|
|||||||
|
|
||||||
impl Format {
|
impl Format {
|
||||||
/// Returns the aspects that images of this format have.
|
/// Returns the aspects that images of this format have.
|
||||||
pub fn aspects(&self) -> ImageAspects {
|
pub fn aspects(self) -> ImageAspects {
|
||||||
ImageAspects {
|
match self {
|
||||||
color: !matches!(self, #(Format::#aspects_color_items)|* ),
|
#(#aspects_items)*
|
||||||
depth: matches!(self, #(Format::#aspects_depth_items)|* ),
|
|
||||||
stencil: matches!(self, #(Format::#aspects_stencil_items)|* ),
|
|
||||||
plane0: matches!(self, #(Format::#aspects_plane0_items)|* ),
|
|
||||||
plane1: matches!(self, #(Format::#aspects_plane1_items)|* ),
|
|
||||||
plane2: matches!(self, #(Format::#aspects_plane2_items)|* ),
|
|
||||||
..ImageAspects::empty()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -403,7 +349,7 @@ fn formats_output(members: &[FormatMember]) -> TokenStream {
|
|||||||
/// a single element. The 422 and 420 YCbCr formats have a block extent of [2, 1, 1] and
|
/// a single element. The 422 and 420 YCbCr formats have a block extent of [2, 1, 1] and
|
||||||
/// [2, 2, 1] respectively, as the red and blue components are shared across multiple
|
/// [2, 2, 1] respectively, as the red and blue components are shared across multiple
|
||||||
/// texels.
|
/// texels.
|
||||||
pub fn block_extent(&self) -> [u32; 3] {
|
pub fn block_extent(self) -> [u32; 3] {
|
||||||
match self {
|
match self {
|
||||||
#(#block_extent_items)*
|
#(#block_extent_items)*
|
||||||
_ => [1, 1, 1],
|
_ => [1, 1, 1],
|
||||||
@ -420,7 +366,7 @@ fn formats_output(members: &[FormatMember]) -> TokenStream {
|
|||||||
/// not have a well-defined size. Multi-planar formats store the color components
|
/// not have a well-defined size. Multi-planar formats store the color components
|
||||||
/// disjointly in memory, and therefore do not have a well-defined size for all
|
/// disjointly in memory, and therefore do not have a well-defined size for all
|
||||||
/// components as a whole. The individual planes do have a well-defined size.
|
/// components as a whole. The individual planes do have a well-defined size.
|
||||||
pub fn block_size(&self) -> Option<DeviceSize> {
|
pub fn block_size(self) -> Option<DeviceSize> {
|
||||||
match self {
|
match self {
|
||||||
#(#block_size_items)*
|
#(#block_size_items)*
|
||||||
_ => None,
|
_ => None,
|
||||||
@ -430,7 +376,7 @@ fn formats_output(members: &[FormatMember]) -> TokenStream {
|
|||||||
/// Returns the an opaque object representing the compatibility class of the format.
|
/// Returns the an opaque object representing the compatibility class of the format.
|
||||||
/// This can be used to determine whether two formats are compatible for the purposes
|
/// This can be used to determine whether two formats are compatible for the purposes
|
||||||
/// of certain Vulkan operations, such as image copying.
|
/// of certain Vulkan operations, such as image copying.
|
||||||
pub fn compatibility(&self) -> FormatCompatibility {
|
pub fn compatibility(self) -> FormatCompatibility {
|
||||||
FormatCompatibility(match self {
|
FormatCompatibility(match self {
|
||||||
#(#compatibility_items)*
|
#(#compatibility_items)*
|
||||||
})
|
})
|
||||||
@ -445,7 +391,7 @@ fn formats_output(members: &[FormatMember]) -> TokenStream {
|
|||||||
/// For block-compressed formats, the number of bits in individual components is not
|
/// For block-compressed formats, the number of bits in individual components is not
|
||||||
/// well-defined, and the return value is merely binary: 1 indicates a component
|
/// well-defined, and the return value is merely binary: 1 indicates a component
|
||||||
/// that is present in the format, 0 indicates one that is absent.
|
/// that is present in the format, 0 indicates one that is absent.
|
||||||
pub fn components(&self) -> [u8; 4] {
|
pub fn components(self) -> [u8; 4] {
|
||||||
match self {
|
match self {
|
||||||
#(#components_items)*
|
#(#components_items)*
|
||||||
}
|
}
|
||||||
@ -453,7 +399,7 @@ fn formats_output(members: &[FormatMember]) -> TokenStream {
|
|||||||
|
|
||||||
/// Returns the block compression scheme used for this format, if any. Returns `None` if
|
/// Returns the block compression scheme used for this format, if any. Returns `None` if
|
||||||
/// the format does not use compression.
|
/// the format does not use compression.
|
||||||
pub fn compression(&self) -> Option<CompressionType> {
|
pub fn compression(self) -> Option<CompressionType> {
|
||||||
match self {
|
match self {
|
||||||
#(#compression_items)*
|
#(#compression_items)*
|
||||||
_ => None,
|
_ => None,
|
||||||
@ -464,7 +410,7 @@ fn formats_output(members: &[FormatMember]) -> TokenStream {
|
|||||||
/// equivalent regular format of each plane.
|
/// equivalent regular format of each plane.
|
||||||
///
|
///
|
||||||
/// For non-planar formats, returns the empty slice.
|
/// For non-planar formats, returns the empty slice.
|
||||||
pub fn planes(&self) -> &'static [Self] {
|
pub fn planes(self) -> &'static [Self] {
|
||||||
match self {
|
match self {
|
||||||
#(#planes_items)*
|
#(#planes_items)*
|
||||||
_ => &[],
|
_ => &[],
|
||||||
@ -473,7 +419,7 @@ fn formats_output(members: &[FormatMember]) -> TokenStream {
|
|||||||
|
|
||||||
/// Returns the number of texels for a single texel block. For most formats, this is
|
/// Returns the number of texels for a single texel block. For most formats, this is
|
||||||
/// the product of the `block_extent` elements, but for some it differs.
|
/// the product of the `block_extent` elements, but for some it differs.
|
||||||
pub fn texels_per_block(&self) -> u8 {
|
pub fn texels_per_block(self) -> u8 {
|
||||||
match self {
|
match self {
|
||||||
#(#texels_per_block_items)*
|
#(#texels_per_block_items)*
|
||||||
_ => 1,
|
_ => 1,
|
||||||
@ -482,7 +428,7 @@ fn formats_output(members: &[FormatMember]) -> TokenStream {
|
|||||||
|
|
||||||
/// Returns the numeric data type of the color aspect of this format. Returns `None`
|
/// Returns the numeric data type of the color aspect of this format. Returns `None`
|
||||||
/// for depth/stencil formats.
|
/// for depth/stencil formats.
|
||||||
pub fn type_color(&self) -> Option<NumericType> {
|
pub fn type_color(self) -> Option<NumericType> {
|
||||||
match self {
|
match self {
|
||||||
#(#type_color_items)*
|
#(#type_color_items)*
|
||||||
_ => None,
|
_ => None,
|
||||||
@ -491,7 +437,7 @@ fn formats_output(members: &[FormatMember]) -> TokenStream {
|
|||||||
|
|
||||||
/// Returns the numeric data type of the depth aspect of this format. Returns `None`
|
/// Returns the numeric data type of the depth aspect of this format. Returns `None`
|
||||||
/// color and stencil-only formats.
|
/// color and stencil-only formats.
|
||||||
pub fn type_depth(&self) -> Option<NumericType> {
|
pub fn type_depth(self) -> Option<NumericType> {
|
||||||
match self {
|
match self {
|
||||||
#(#type_depth_items)*
|
#(#type_depth_items)*
|
||||||
_ => None,
|
_ => None,
|
||||||
@ -500,7 +446,7 @@ fn formats_output(members: &[FormatMember]) -> TokenStream {
|
|||||||
|
|
||||||
/// Returns the numeric data type of the stencil aspect of this format. Returns `None`
|
/// Returns the numeric data type of the stencil aspect of this format. Returns `None`
|
||||||
/// for color and depth-only formats.
|
/// for color and depth-only formats.
|
||||||
pub fn type_stencil(&self) -> Option<NumericType> {
|
pub fn type_stencil(self) -> Option<NumericType> {
|
||||||
match self {
|
match self {
|
||||||
#(#type_stencil_items)*
|
#(#type_stencil_items)*
|
||||||
_ => None,
|
_ => None,
|
||||||
@ -513,7 +459,7 @@ fn formats_output(members: &[FormatMember]) -> TokenStream {
|
|||||||
/// If an image view is created for one of the formats for which this function returns
|
/// If an image view is created for one of the formats for which this function returns
|
||||||
/// `Some`, with the `color` aspect selected, then the view and any samplers that sample
|
/// `Some`, with the `color` aspect selected, then the view and any samplers that sample
|
||||||
/// it must be created with an attached sampler YCbCr conversion object.
|
/// it must be created with an attached sampler YCbCr conversion object.
|
||||||
pub fn ycbcr_chroma_sampling(&self) -> Option<ChromaSampling> {
|
pub fn ycbcr_chroma_sampling(self) -> Option<ChromaSampling> {
|
||||||
match self {
|
match self {
|
||||||
#(#ycbcr_chroma_sampling_items)*
|
#(#ycbcr_chroma_sampling_items)*
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@ -432,6 +432,7 @@ fn suffix_key(name: &str) -> u32 {
|
|||||||
static ref VENDOR_SUFFIXES: Regex = Regex::new(r"(?:AMD|GOOGLE|INTEL|NV)$").unwrap();
|
static ref VENDOR_SUFFIXES: Regex = Regex::new(r"(?:AMD|GOOGLE|INTEL|NV)$").unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::bool_to_int_with_if)]
|
||||||
if VENDOR_SUFFIXES.is_match(name) {
|
if VENDOR_SUFFIXES.is_match(name) {
|
||||||
3
|
3
|
||||||
} else if name.ends_with("EXT") {
|
} else if name.ends_with("EXT") {
|
||||||
|
@ -63,7 +63,7 @@ enum Enable {
|
|||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
enum PropertyValue {
|
enum PropertyValue {
|
||||||
Bool,
|
Bool,
|
||||||
BoolMember(Ident),
|
BoolMember(Vec<Ident>),
|
||||||
}
|
}
|
||||||
|
|
||||||
fn spirv_reqs_output(members: &[SpirvReqsMember], extension: bool) -> TokenStream {
|
fn spirv_reqs_output(members: &[SpirvReqsMember], extension: bool) -> TokenStream {
|
||||||
@ -97,7 +97,7 @@ fn spirv_reqs_output(members: &[SpirvReqsMember], extension: bool) -> TokenStrea
|
|||||||
let access = match value {
|
let access = match value {
|
||||||
PropertyValue::Bool => quote! {},
|
PropertyValue::Bool => quote! {},
|
||||||
PropertyValue::BoolMember(member) => quote! {
|
PropertyValue::BoolMember(member) => quote! {
|
||||||
.map(|x| x.#member)
|
.map(|x| x.intersects(#(#member)::*))
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -249,9 +249,14 @@ fn make_enable(enable: &vk_parse::Enable) -> Option<(Enable, String)> {
|
|||||||
let (value, description) = if property.value == "VK_TRUE" {
|
let (value, description) = if property.value == "VK_TRUE" {
|
||||||
(PropertyValue::Bool, format!("property `{}`", property_name))
|
(PropertyValue::Bool, format!("property `{}`", property_name))
|
||||||
} else if let Some(member) = property.value.strip_prefix("VK_SUBGROUP_FEATURE_") {
|
} else if let Some(member) = property.value.strip_prefix("VK_SUBGROUP_FEATURE_") {
|
||||||
let member = BIT.replace(member, "").to_snake_case();
|
let member = BIT.replace(member, "");
|
||||||
(
|
(
|
||||||
PropertyValue::BoolMember(format_ident!("{}", member)),
|
PropertyValue::BoolMember(
|
||||||
|
["crate", "device", "physical", "SubgroupFeatures", &member]
|
||||||
|
.into_iter()
|
||||||
|
.map(|s| format_ident!("{}", s))
|
||||||
|
.collect(),
|
||||||
|
),
|
||||||
format!("property `{}.{}`", property_name, member),
|
format!("property `{}.{}`", property_name, member),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
@ -578,20 +578,14 @@ mod tests {
|
|||||||
assert_should_panic!({
|
assert_should_panic!({
|
||||||
CpuAccessibleBuffer::from_data(
|
CpuAccessibleBuffer::from_data(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::TRANSFER_DST,
|
||||||
transfer_dst: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
EMPTY,
|
EMPTY,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
CpuAccessibleBuffer::from_iter(
|
CpuAccessibleBuffer::from_iter(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::TRANSFER_DST,
|
||||||
transfer_dst: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
EMPTY.into_iter(),
|
EMPTY.into_iter(),
|
||||||
)
|
)
|
||||||
|
@ -216,14 +216,7 @@ where
|
|||||||
///
|
///
|
||||||
/// - Panics if `T` has zero size.
|
/// - Panics if `T` has zero size.
|
||||||
pub fn upload(allocator: Arc<A>) -> CpuBufferPool<T, A> {
|
pub fn upload(allocator: Arc<A>) -> CpuBufferPool<T, A> {
|
||||||
CpuBufferPool::new(
|
CpuBufferPool::new(allocator, BufferUsage::TRANSFER_SRC, MemoryUsage::Upload)
|
||||||
allocator,
|
|
||||||
BufferUsage {
|
|
||||||
transfer_src: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
MemoryUsage::Upload,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds a `CpuBufferPool` meant for simple downloads.
|
/// Builds a `CpuBufferPool` meant for simple downloads.
|
||||||
@ -235,14 +228,7 @@ where
|
|||||||
///
|
///
|
||||||
/// - Panics if `T` has zero size.
|
/// - Panics if `T` has zero size.
|
||||||
pub fn download(allocator: Arc<A>) -> CpuBufferPool<T, A> {
|
pub fn download(allocator: Arc<A>) -> CpuBufferPool<T, A> {
|
||||||
CpuBufferPool::new(
|
CpuBufferPool::new(allocator, BufferUsage::TRANSFER_DST, MemoryUsage::Download)
|
||||||
allocator,
|
|
||||||
BufferUsage {
|
|
||||||
transfer_dst: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
MemoryUsage::Download,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds a `CpuBufferPool` meant for usage as a uniform buffer.
|
/// Builds a `CpuBufferPool` meant for usage as a uniform buffer.
|
||||||
@ -254,14 +240,7 @@ where
|
|||||||
///
|
///
|
||||||
/// - Panics if `T` has zero size.
|
/// - Panics if `T` has zero size.
|
||||||
pub fn uniform_buffer(allocator: Arc<A>) -> CpuBufferPool<T, A> {
|
pub fn uniform_buffer(allocator: Arc<A>) -> CpuBufferPool<T, A> {
|
||||||
CpuBufferPool::new(
|
CpuBufferPool::new(allocator, BufferUsage::UNIFORM_BUFFER, MemoryUsage::Upload)
|
||||||
allocator,
|
|
||||||
BufferUsage {
|
|
||||||
uniform_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
MemoryUsage::Upload,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds a `CpuBufferPool` meant for usage as a vertex buffer.
|
/// Builds a `CpuBufferPool` meant for usage as a vertex buffer.
|
||||||
@ -273,14 +252,7 @@ where
|
|||||||
///
|
///
|
||||||
/// - Panics if `T` has zero size.
|
/// - Panics if `T` has zero size.
|
||||||
pub fn vertex_buffer(allocator: Arc<A>) -> CpuBufferPool<T, A> {
|
pub fn vertex_buffer(allocator: Arc<A>) -> CpuBufferPool<T, A> {
|
||||||
CpuBufferPool::new(
|
CpuBufferPool::new(allocator, BufferUsage::VERTEX_BUFFER, MemoryUsage::Upload)
|
||||||
allocator,
|
|
||||||
BufferUsage {
|
|
||||||
vertex_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
MemoryUsage::Upload,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds a `CpuBufferPool` meant for usage as a indirect buffer.
|
/// Builds a `CpuBufferPool` meant for usage as a indirect buffer.
|
||||||
@ -292,14 +264,7 @@ where
|
|||||||
///
|
///
|
||||||
/// - Panics if `T` has zero size.
|
/// - Panics if `T` has zero size.
|
||||||
pub fn indirect_buffer(allocator: Arc<A>) -> CpuBufferPool<T, A> {
|
pub fn indirect_buffer(allocator: Arc<A>) -> CpuBufferPool<T, A> {
|
||||||
CpuBufferPool::new(
|
CpuBufferPool::new(allocator, BufferUsage::INDIRECT_BUFFER, MemoryUsage::Upload)
|
||||||
allocator,
|
|
||||||
BufferUsage {
|
|
||||||
indirect_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
MemoryUsage::Upload,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -538,7 +503,7 @@ where
|
|||||||
let idx = current_buffer.next_index.load(Ordering::SeqCst);
|
let idx = current_buffer.next_index.load(Ordering::SeqCst);
|
||||||
|
|
||||||
// Find the required alignment in bytes.
|
// Find the required alignment in bytes.
|
||||||
let align_uniform = if self.buffer_usage.uniform_buffer {
|
let align_uniform = if self.buffer_usage.intersects(BufferUsage::UNIFORM_BUFFER) {
|
||||||
self.device()
|
self.device()
|
||||||
.physical_device()
|
.physical_device()
|
||||||
.properties()
|
.properties()
|
||||||
@ -546,7 +511,7 @@ where
|
|||||||
} else {
|
} else {
|
||||||
1
|
1
|
||||||
};
|
};
|
||||||
let align_storage = if self.buffer_usage.storage_buffer {
|
let align_storage = if self.buffer_usage.intersects(BufferUsage::STORAGE_BUFFER) {
|
||||||
self.device()
|
self.device()
|
||||||
.physical_device()
|
.physical_device()
|
||||||
.properties()
|
.properties()
|
||||||
|
@ -83,7 +83,8 @@ use std::{
|
|||||||
/// // Create a CPU accessible buffer initialized with the data.
|
/// // Create a CPU accessible buffer initialized with the data.
|
||||||
/// let temporary_accessible_buffer = CpuAccessibleBuffer::from_iter(
|
/// let temporary_accessible_buffer = CpuAccessibleBuffer::from_iter(
|
||||||
/// &memory_allocator,
|
/// &memory_allocator,
|
||||||
/// BufferUsage { transfer_src: true, ..BufferUsage::empty() }, // Specify this buffer will be used as a transfer source.
|
/// // Specify this buffer will be used as a transfer source.
|
||||||
|
/// BufferUsage::TRANSFER_SRC,
|
||||||
/// false,
|
/// false,
|
||||||
/// data,
|
/// data,
|
||||||
/// )
|
/// )
|
||||||
@ -93,11 +94,8 @@ use std::{
|
|||||||
/// let device_local_buffer = DeviceLocalBuffer::<[f32]>::array(
|
/// let device_local_buffer = DeviceLocalBuffer::<[f32]>::array(
|
||||||
/// &memory_allocator,
|
/// &memory_allocator,
|
||||||
/// 10_000 as vulkano::DeviceSize,
|
/// 10_000 as vulkano::DeviceSize,
|
||||||
/// BufferUsage {
|
/// // Specify use as a storage buffer and transfer destination.
|
||||||
/// storage_buffer: true,
|
/// BufferUsage::STORAGE_BUFFER | BufferUsage::TRANSFER_DST,
|
||||||
/// transfer_dst: true,
|
|
||||||
/// ..BufferUsage::empty()
|
|
||||||
/// }, // Specify use as a storage buffer and transfer destination.
|
|
||||||
/// device.active_queue_family_indices().iter().copied(),
|
/// device.active_queue_family_indices().iter().copied(),
|
||||||
/// )
|
/// )
|
||||||
/// .unwrap();
|
/// .unwrap();
|
||||||
@ -182,10 +180,7 @@ where
|
|||||||
{
|
{
|
||||||
unsafe {
|
unsafe {
|
||||||
// We automatically set `transfer_dst` to true in order to avoid annoying errors.
|
// We automatically set `transfer_dst` to true in order to avoid annoying errors.
|
||||||
let actual_usage = BufferUsage {
|
let actual_usage = usage | BufferUsage::TRANSFER_DST;
|
||||||
transfer_dst: true,
|
|
||||||
..usage
|
|
||||||
};
|
|
||||||
|
|
||||||
let buffer = DeviceLocalBuffer::raw(
|
let buffer = DeviceLocalBuffer::raw(
|
||||||
allocator,
|
allocator,
|
||||||
@ -229,15 +224,8 @@ where
|
|||||||
where
|
where
|
||||||
A: CommandBufferAllocator,
|
A: CommandBufferAllocator,
|
||||||
{
|
{
|
||||||
let source = CpuAccessibleBuffer::from_data(
|
let source =
|
||||||
allocator,
|
CpuAccessibleBuffer::from_data(allocator, BufferUsage::TRANSFER_SRC, false, data)?;
|
||||||
BufferUsage {
|
|
||||||
transfer_src: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
|
||||||
data,
|
|
||||||
)?;
|
|
||||||
DeviceLocalBuffer::from_buffer(allocator, source, usage, command_buffer_builder)
|
DeviceLocalBuffer::from_buffer(allocator, source, usage, command_buffer_builder)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -267,15 +255,8 @@ where
|
|||||||
D::IntoIter: ExactSizeIterator,
|
D::IntoIter: ExactSizeIterator,
|
||||||
A: CommandBufferAllocator,
|
A: CommandBufferAllocator,
|
||||||
{
|
{
|
||||||
let source = CpuAccessibleBuffer::from_iter(
|
let source =
|
||||||
allocator,
|
CpuAccessibleBuffer::from_iter(allocator, BufferUsage::TRANSFER_SRC, false, data)?;
|
||||||
BufferUsage {
|
|
||||||
transfer_src: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
|
||||||
data,
|
|
||||||
)?;
|
|
||||||
DeviceLocalBuffer::from_buffer(allocator, source, usage, command_buffer_builder)
|
DeviceLocalBuffer::from_buffer(allocator, source, usage, command_buffer_builder)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -407,10 +388,7 @@ where
|
|||||||
// VUID-VkMemoryAllocateInfo-pNext-00639
|
// VUID-VkMemoryAllocateInfo-pNext-00639
|
||||||
// Guaranteed because we always create a dedicated allocation
|
// Guaranteed because we always create a dedicated allocation
|
||||||
|
|
||||||
let external_memory_handle_types = ExternalMemoryHandleTypes {
|
let external_memory_handle_types = ExternalMemoryHandleTypes::OPAQUE_FD;
|
||||||
opaque_fd: true,
|
|
||||||
..ExternalMemoryHandleTypes::empty()
|
|
||||||
};
|
|
||||||
let raw_buffer = RawBuffer::new(
|
let raw_buffer = RawBuffer::new(
|
||||||
allocator.device().clone(),
|
allocator.device().clone(),
|
||||||
BufferCreateInfo {
|
BufferCreateInfo {
|
||||||
@ -570,24 +548,14 @@ mod tests {
|
|||||||
let buffer = DeviceLocalBuffer::from_data(
|
let buffer = DeviceLocalBuffer::from_data(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
12u32,
|
12u32,
|
||||||
BufferUsage {
|
BufferUsage::TRANSFER_SRC,
|
||||||
transfer_src: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
&mut command_buffer_builder,
|
&mut command_buffer_builder,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let destination = CpuAccessibleBuffer::from_data(
|
let destination =
|
||||||
&memory_allocator,
|
CpuAccessibleBuffer::from_data(&memory_allocator, BufferUsage::TRANSFER_DST, false, 0)
|
||||||
BufferUsage {
|
.unwrap();
|
||||||
transfer_dst: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
|
||||||
0,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
command_buffer_builder
|
command_buffer_builder
|
||||||
.copy_buffer(CopyBufferInfo::buffers(buffer, destination.clone()))
|
.copy_buffer(CopyBufferInfo::buffers(buffer, destination.clone()))
|
||||||
@ -621,20 +589,14 @@ mod tests {
|
|||||||
let buffer = DeviceLocalBuffer::from_iter(
|
let buffer = DeviceLocalBuffer::from_iter(
|
||||||
&allocator,
|
&allocator,
|
||||||
(0..512u32).map(|n| n * 2),
|
(0..512u32).map(|n| n * 2),
|
||||||
BufferUsage {
|
BufferUsage::TRANSFER_SRC,
|
||||||
transfer_src: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
&mut command_buffer_builder,
|
&mut command_buffer_builder,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let destination = CpuAccessibleBuffer::from_iter(
|
let destination = CpuAccessibleBuffer::from_iter(
|
||||||
&allocator,
|
&allocator,
|
||||||
BufferUsage {
|
BufferUsage::TRANSFER_DST,
|
||||||
transfer_dst: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
(0..512).map(|_| 0u32),
|
(0..512).map(|_| 0u32),
|
||||||
)
|
)
|
||||||
@ -676,10 +638,7 @@ mod tests {
|
|||||||
DeviceLocalBuffer::from_data(
|
DeviceLocalBuffer::from_data(
|
||||||
&allocator,
|
&allocator,
|
||||||
(),
|
(),
|
||||||
BufferUsage {
|
BufferUsage::TRANSFER_DST,
|
||||||
transfer_dst: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
&mut command_buffer_builder,
|
&mut command_buffer_builder,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -106,8 +106,9 @@ mod traits;
|
|||||||
mod usage;
|
mod usage;
|
||||||
|
|
||||||
vulkan_bitflags! {
|
vulkan_bitflags! {
|
||||||
/// Flags to be set when creating a buffer.
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
|
|
||||||
|
/// Flags to be set when creating a buffer.
|
||||||
BufferCreateFlags = BufferCreateFlags(u32);
|
BufferCreateFlags = BufferCreateFlags(u32);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -118,7 +119,7 @@ vulkan_bitflags! {
|
|||||||
///
|
///
|
||||||
/// [`bind_memory`]: sys::RawBuffer::bind_memory
|
/// [`bind_memory`]: sys::RawBuffer::bind_memory
|
||||||
/// [`sparse_binding`]: crate::device::Features::sparse_binding
|
/// [`sparse_binding`]: crate::device::Features::sparse_binding
|
||||||
sparse_binding = SPARSE_BINDING,
|
SPARSE_BINDING = SPARSE_BINDING,
|
||||||
|
|
||||||
/// The buffer can be used without being fully resident in memory at the time of use.
|
/// The buffer can be used without being fully resident in memory at the time of use.
|
||||||
///
|
///
|
||||||
@ -127,7 +128,7 @@ vulkan_bitflags! {
|
|||||||
/// The [`sparse_residency_buffer`] feature must be enabled on the device.
|
/// The [`sparse_residency_buffer`] feature must be enabled on the device.
|
||||||
///
|
///
|
||||||
/// [`sparse_residency_buffer`]: crate::device::Features::sparse_residency_buffer
|
/// [`sparse_residency_buffer`]: crate::device::Features::sparse_residency_buffer
|
||||||
sparse_residency = SPARSE_RESIDENCY,
|
SPARSE_RESIDENCY = SPARSE_RESIDENCY,
|
||||||
|
|
||||||
/// The buffer's memory can alias with another buffer or a different part of the same buffer.
|
/// The buffer's memory can alias with another buffer or a different part of the same buffer.
|
||||||
///
|
///
|
||||||
@ -136,13 +137,13 @@ vulkan_bitflags! {
|
|||||||
/// The [`sparse_residency_aliased`] feature must be enabled on the device.
|
/// The [`sparse_residency_aliased`] feature must be enabled on the device.
|
||||||
///
|
///
|
||||||
/// [`sparse_residency_aliased`]: crate::device::Features::sparse_residency_aliased
|
/// [`sparse_residency_aliased`]: crate::device::Features::sparse_residency_aliased
|
||||||
sparse_aliased = SPARSE_ALIASED,
|
SPARSE_ALIASED = SPARSE_ALIASED,
|
||||||
|
|
||||||
/// The buffer is protected, and can only be used in combination with protected memory and other
|
/// The buffer is protected, and can only be used in combination with protected memory and other
|
||||||
/// protected objects.
|
/// protected objects.
|
||||||
///
|
///
|
||||||
/// The device API version must be at least 1.1.
|
/// The device API version must be at least 1.1.
|
||||||
protected = PROTECTED {
|
PROTECTED = PROTECTED {
|
||||||
api_version: V1_1,
|
api_version: V1_1,
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -150,7 +151,7 @@ vulkan_bitflags! {
|
|||||||
///
|
///
|
||||||
/// The device API version must be at least 1.2, or either the [`khr_buffer_device_address`] or
|
/// The device API version must be at least 1.2, or either the [`khr_buffer_device_address`] or
|
||||||
/// [`ext_buffer_device_address`] extension must be enabled on the device.
|
/// [`ext_buffer_device_address`] extension must be enabled on the device.
|
||||||
device_address_capture_replay = DEVICE_ADDRESS_CAPTURE_REPLAY {
|
DEVICE_ADDRESS_CAPTURE_REPLAY = DEVICE_ADDRESS_CAPTURE_REPLAY {
|
||||||
api_version: V1_2,
|
api_version: V1_2,
|
||||||
device_extensions: [khr_buffer_device_address, ext_buffer_device_address],
|
device_extensions: [khr_buffer_device_address, ext_buffer_device_address],
|
||||||
},
|
},
|
||||||
|
@ -21,7 +21,8 @@ use crate::{
|
|||||||
device::{Device, DeviceOwned},
|
device::{Device, DeviceOwned},
|
||||||
memory::{
|
memory::{
|
||||||
allocator::{AllocationCreationError, MemoryAlloc},
|
allocator::{AllocationCreationError, MemoryAlloc},
|
||||||
DedicatedTo, ExternalMemoryHandleType, ExternalMemoryHandleTypes, MemoryRequirements,
|
DedicatedTo, ExternalMemoryHandleType, ExternalMemoryHandleTypes, MemoryAllocateFlags,
|
||||||
|
MemoryPropertyFlags, MemoryRequirements,
|
||||||
},
|
},
|
||||||
range_map::RangeMap,
|
range_map::RangeMap,
|
||||||
sync::{AccessError, CurrentAccess, Sharing},
|
sync::{AccessError, CurrentAccess, Sharing},
|
||||||
@ -126,7 +127,8 @@ impl RawBuffer {
|
|||||||
// VUID-VkBufferCreateInfo-flags-00916
|
// VUID-VkBufferCreateInfo-flags-00916
|
||||||
if sparse_level.sparse_residency && !device.enabled_features().sparse_residency_buffer {
|
if sparse_level.sparse_residency && !device.enabled_features().sparse_residency_buffer {
|
||||||
return Err(BufferError::RequirementNotMet {
|
return Err(BufferError::RequirementNotMet {
|
||||||
required_for: "`create_info.sparse` is `Some(sparse_level)`, where `sparse_level.sparse_residency` is set",
|
required_for: "`create_info.sparse` is `Some(sparse_level)`, where \
|
||||||
|
`sparse_level` contains `BufferCreateFlags::SPARSE_RESIDENCY`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["sparse_residency_buffer"],
|
features: &["sparse_residency_buffer"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -137,7 +139,8 @@ impl RawBuffer {
|
|||||||
// VUID-VkBufferCreateInfo-flags-00917
|
// VUID-VkBufferCreateInfo-flags-00917
|
||||||
if sparse_level.sparse_aliased && !device.enabled_features().sparse_residency_aliased {
|
if sparse_level.sparse_aliased && !device.enabled_features().sparse_residency_aliased {
|
||||||
return Err(BufferError::RequirementNotMet {
|
return Err(BufferError::RequirementNotMet {
|
||||||
required_for: "`create_info.sparse` is `Some(sparse_level)`, where `sparse_level.sparse_aliased` is set",
|
required_for: "`create_info.sparse` is `Some(sparse_level)`, where \
|
||||||
|
`sparse_level` contains `BufferCreateFlags::SPARSE_ALIASED`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["sparse_residency_aliased"],
|
features: &["sparse_residency_aliased"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -302,21 +305,21 @@ impl RawBuffer {
|
|||||||
|
|
||||||
// We have to manually enforce some additional requirements for some buffer types.
|
// We have to manually enforce some additional requirements for some buffer types.
|
||||||
let properties = device.physical_device().properties();
|
let properties = device.physical_device().properties();
|
||||||
if usage.uniform_texel_buffer || usage.storage_texel_buffer {
|
if usage.intersects(BufferUsage::UNIFORM_TEXEL_BUFFER | BufferUsage::STORAGE_TEXEL_BUFFER) {
|
||||||
memory_requirements.alignment = align(
|
memory_requirements.alignment = align(
|
||||||
memory_requirements.alignment,
|
memory_requirements.alignment,
|
||||||
properties.min_texel_buffer_offset_alignment,
|
properties.min_texel_buffer_offset_alignment,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if usage.storage_buffer {
|
if usage.intersects(BufferUsage::STORAGE_BUFFER) {
|
||||||
memory_requirements.alignment = align(
|
memory_requirements.alignment = align(
|
||||||
memory_requirements.alignment,
|
memory_requirements.alignment,
|
||||||
properties.min_storage_buffer_offset_alignment,
|
properties.min_storage_buffer_offset_alignment,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if usage.uniform_buffer {
|
if usage.intersects(BufferUsage::UNIFORM_BUFFER) {
|
||||||
memory_requirements.alignment = align(
|
memory_requirements.alignment = align(
|
||||||
memory_requirements.alignment,
|
memory_requirements.alignment,
|
||||||
properties.min_uniform_buffer_offset_alignment,
|
properties.min_uniform_buffer_offset_alignment,
|
||||||
@ -479,7 +482,10 @@ impl RawBuffer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VUID-VkBindBufferMemoryInfo-None-01899
|
// VUID-VkBindBufferMemoryInfo-None-01899
|
||||||
if memory_type.property_flags.protected {
|
if memory_type
|
||||||
|
.property_flags
|
||||||
|
.intersects(MemoryPropertyFlags::PROTECTED)
|
||||||
|
{
|
||||||
return Err(BufferError::MemoryProtectedMismatch {
|
return Err(BufferError::MemoryProtectedMismatch {
|
||||||
buffer_protected: false,
|
buffer_protected: false,
|
||||||
memory_protected: true,
|
memory_protected: true,
|
||||||
@ -490,7 +496,7 @@ impl RawBuffer {
|
|||||||
if !memory.export_handle_types().is_empty()
|
if !memory.export_handle_types().is_empty()
|
||||||
&& !memory
|
&& !memory
|
||||||
.export_handle_types()
|
.export_handle_types()
|
||||||
.intersects(&self.external_memory_handle_types)
|
.intersects(self.external_memory_handle_types)
|
||||||
{
|
{
|
||||||
return Err(BufferError::MemoryExternalHandleTypesDisjoint {
|
return Err(BufferError::MemoryExternalHandleTypesDisjoint {
|
||||||
buffer_handle_types: self.external_memory_handle_types,
|
buffer_handle_types: self.external_memory_handle_types,
|
||||||
@ -501,7 +507,7 @@ impl RawBuffer {
|
|||||||
if let Some(handle_type) = memory.imported_handle_type() {
|
if let Some(handle_type) = memory.imported_handle_type() {
|
||||||
// VUID-VkBindBufferMemoryInfo-memory-02985
|
// VUID-VkBindBufferMemoryInfo-memory-02985
|
||||||
if !ExternalMemoryHandleTypes::from(handle_type)
|
if !ExternalMemoryHandleTypes::from(handle_type)
|
||||||
.intersects(&self.external_memory_handle_types)
|
.intersects(self.external_memory_handle_types)
|
||||||
{
|
{
|
||||||
return Err(BufferError::MemoryImportedHandleTypeNotEnabled {
|
return Err(BufferError::MemoryImportedHandleTypeNotEnabled {
|
||||||
buffer_handle_types: self.external_memory_handle_types,
|
buffer_handle_types: self.external_memory_handle_types,
|
||||||
@ -512,8 +518,10 @@ impl RawBuffer {
|
|||||||
|
|
||||||
// VUID-VkBindBufferMemoryInfo-bufferDeviceAddress-03339
|
// VUID-VkBindBufferMemoryInfo-bufferDeviceAddress-03339
|
||||||
if !self.device.enabled_extensions().ext_buffer_device_address
|
if !self.device.enabled_extensions().ext_buffer_device_address
|
||||||
&& self.usage.shader_device_address
|
&& self.usage.intersects(BufferUsage::SHADER_DEVICE_ADDRESS)
|
||||||
&& !memory.flags().device_address
|
&& !memory
|
||||||
|
.flags()
|
||||||
|
.intersects(MemoryAllocateFlags::DEVICE_ADDRESS)
|
||||||
{
|
{
|
||||||
return Err(BufferError::MemoryBufferDeviceAddressNotSupported);
|
return Err(BufferError::MemoryBufferDeviceAddressNotSupported);
|
||||||
}
|
}
|
||||||
@ -660,11 +668,12 @@ pub struct BufferCreateInfo {
|
|||||||
|
|
||||||
/// The external memory handle types that are going to be used with the buffer.
|
/// The external memory handle types that are going to be used with the buffer.
|
||||||
///
|
///
|
||||||
/// If any of the fields in this value are set, the device must either support API version 1.1
|
/// If this value is not empty, then the device API version must be at least 1.1, or the
|
||||||
/// or the [`khr_external_memory`](crate::device::DeviceExtensions::khr_external_memory)
|
/// [`khr_external_memory`] extension must be enabled on the device.
|
||||||
/// extension must be enabled.
|
|
||||||
///
|
///
|
||||||
/// The default value is [`ExternalMemoryHandleTypes::empty()`].
|
/// The default value is [`ExternalMemoryHandleTypes::empty()`].
|
||||||
|
///
|
||||||
|
/// [`khr_external_memory`]: crate::device::DeviceExtensions::khr_external_memory
|
||||||
pub external_memory_handle_types: ExternalMemoryHandleTypes,
|
pub external_memory_handle_types: ExternalMemoryHandleTypes,
|
||||||
|
|
||||||
pub _ne: crate::NonExhaustive,
|
pub _ne: crate::NonExhaustive,
|
||||||
@ -1429,10 +1438,7 @@ mod tests {
|
|||||||
device.clone(),
|
device.clone(),
|
||||||
BufferCreateInfo {
|
BufferCreateInfo {
|
||||||
size: 128,
|
size: 128,
|
||||||
usage: BufferUsage {
|
usage: BufferUsage::TRANSFER_DST,
|
||||||
transfer_dst: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -1453,10 +1459,7 @@ mod tests {
|
|||||||
BufferCreateInfo {
|
BufferCreateInfo {
|
||||||
size: 128,
|
size: 128,
|
||||||
sparse: Some(BufferCreateFlags::empty()),
|
sparse: Some(BufferCreateFlags::empty()),
|
||||||
usage: BufferUsage {
|
usage: BufferUsage::transfer_dst,
|
||||||
transfer_dst: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
@ -1480,10 +1483,7 @@ mod tests {
|
|||||||
sparse_aliased: false,
|
sparse_aliased: false,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
usage: BufferUsage {
|
usage: BufferUsage::transfer_dst,
|
||||||
transfer_dst: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
@ -1507,10 +1507,7 @@ mod tests {
|
|||||||
sparse_aliased: true,
|
sparse_aliased: true,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
usage: BufferUsage {
|
usage: BufferUsage::transfer_dst,
|
||||||
transfer_dst: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
@ -1532,10 +1529,7 @@ mod tests {
|
|||||||
device,
|
device,
|
||||||
BufferCreateInfo {
|
BufferCreateInfo {
|
||||||
size: 0,
|
size: 0,
|
||||||
usage: BufferUsage {
|
usage: BufferUsage::TRANSFER_DST,
|
||||||
transfer_dst: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -81,7 +81,7 @@ pub unsafe trait BufferAccess: DeviceOwned + Send + Sync {
|
|||||||
// VUID-vkGetBufferDeviceAddress-bufferDeviceAddress-03324
|
// VUID-vkGetBufferDeviceAddress-bufferDeviceAddress-03324
|
||||||
if !device.enabled_features().buffer_device_address {
|
if !device.enabled_features().buffer_device_address {
|
||||||
return Err(BufferDeviceAddressError::RequirementNotMet {
|
return Err(BufferDeviceAddressError::RequirementNotMet {
|
||||||
required_for: "`raw_device_address`",
|
required_for: "`BufferAccess::raw_device_address`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["buffer_device_address"],
|
features: &["buffer_device_address"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -90,7 +90,11 @@ pub unsafe trait BufferAccess: DeviceOwned + Send + Sync {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VUID-VkBufferDeviceAddressInfo-buffer-02601
|
// VUID-VkBufferDeviceAddressInfo-buffer-02601
|
||||||
if !inner.buffer.usage().shader_device_address {
|
if !inner
|
||||||
|
.buffer
|
||||||
|
.usage()
|
||||||
|
.intersects(BufferUsage::SHADER_DEVICE_ADDRESS)
|
||||||
|
{
|
||||||
return Err(BufferDeviceAddressError::BufferMissingUsage);
|
return Err(BufferDeviceAddressError::BufferMissingUsage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,100 +10,101 @@
|
|||||||
use crate::macros::vulkan_bitflags;
|
use crate::macros::vulkan_bitflags;
|
||||||
|
|
||||||
vulkan_bitflags! {
|
vulkan_bitflags! {
|
||||||
|
#[non_exhaustive]
|
||||||
|
|
||||||
/// Describes how a buffer is going to be used. This is **not** just an optimization.
|
/// Describes how a buffer is going to be used. This is **not** just an optimization.
|
||||||
///
|
///
|
||||||
/// If you try to use a buffer in a way that you didn't declare, an error will be returned.
|
/// If you try to use a buffer in a way that you didn't declare, an error will be returned.
|
||||||
#[non_exhaustive]
|
|
||||||
BufferUsage = BufferUsageFlags(u32);
|
BufferUsage = BufferUsageFlags(u32);
|
||||||
|
|
||||||
/// The buffer can be used as a source for transfer, blit, resolve and clear commands.
|
/// The buffer can be used as a source for transfer, blit, resolve and clear commands.
|
||||||
transfer_src = TRANSFER_SRC,
|
TRANSFER_SRC = TRANSFER_SRC,
|
||||||
|
|
||||||
/// The buffer can be used as a destination for transfer, blit, resolve and clear commands.
|
/// The buffer can be used as a destination for transfer, blit, resolve and clear commands.
|
||||||
transfer_dst = TRANSFER_DST,
|
TRANSFER_DST = TRANSFER_DST,
|
||||||
|
|
||||||
/// The buffer can be used as a uniform texel buffer in a descriptor set.
|
/// The buffer can be used as a uniform texel buffer in a descriptor set.
|
||||||
uniform_texel_buffer = UNIFORM_TEXEL_BUFFER,
|
UNIFORM_TEXEL_BUFFER = UNIFORM_TEXEL_BUFFER,
|
||||||
|
|
||||||
/// The buffer can be used as a storage texel buffer in a descriptor set.
|
/// The buffer can be used as a storage texel buffer in a descriptor set.
|
||||||
storage_texel_buffer = STORAGE_TEXEL_BUFFER,
|
STORAGE_TEXEL_BUFFER = STORAGE_TEXEL_BUFFER,
|
||||||
|
|
||||||
/// The buffer can be used as a uniform buffer in a descriptor set.
|
/// The buffer can be used as a uniform buffer in a descriptor set.
|
||||||
uniform_buffer = UNIFORM_BUFFER,
|
UNIFORM_BUFFER = UNIFORM_BUFFER,
|
||||||
|
|
||||||
/// The buffer can be used as a storage buffer in a descriptor set.
|
/// The buffer can be used as a storage buffer in a descriptor set.
|
||||||
storage_buffer = STORAGE_BUFFER,
|
STORAGE_BUFFER = STORAGE_BUFFER,
|
||||||
|
|
||||||
/// The buffer can be used as an index buffer.
|
/// The buffer can be used as an index buffer.
|
||||||
index_buffer = INDEX_BUFFER,
|
INDEX_BUFFER = INDEX_BUFFER,
|
||||||
|
|
||||||
/// The buffer can be used as a vertex or instance buffer.
|
/// The buffer can be used as a vertex or instance buffer.
|
||||||
vertex_buffer = VERTEX_BUFFER,
|
VERTEX_BUFFER = VERTEX_BUFFER,
|
||||||
|
|
||||||
/// The buffer can be used as an indirect buffer.
|
/// The buffer can be used as an indirect buffer.
|
||||||
indirect_buffer = INDIRECT_BUFFER,
|
INDIRECT_BUFFER = INDIRECT_BUFFER,
|
||||||
|
|
||||||
/// The buffer's device address can be retrieved.
|
/// The buffer's device address can be retrieved.
|
||||||
///
|
///
|
||||||
/// A buffer created with this usage can only be bound to device memory allocated with the
|
/// A buffer created with this usage can only be bound to device memory allocated with the
|
||||||
/// [`device_address`] flag set unless the [`ext_buffer_device_address`] extension is enabled
|
/// [`MemoryAllocateFlags::DEVICE_ADDRESS`] flag, unless the [`ext_buffer_device_address`]
|
||||||
/// on the device.
|
/// extension is enabled on the device.
|
||||||
///
|
///
|
||||||
/// [`device_address`]: crate::memory::MemoryAllocateFlags::device_address
|
/// [`MemoryAllocateFlags::DEVICE_ADDRESS`]: crate::memory::MemoryAllocateFlags::DEVICE_ADDRESS
|
||||||
/// [`ext_buffer_device_address`]: crate::device::DeviceExtensions::ext_buffer_device_address
|
/// [`ext_buffer_device_address`]: crate::device::DeviceExtensions::ext_buffer_device_address
|
||||||
shader_device_address = SHADER_DEVICE_ADDRESS {
|
SHADER_DEVICE_ADDRESS = SHADER_DEVICE_ADDRESS {
|
||||||
api_version: V1_2,
|
api_version: V1_2,
|
||||||
device_extensions: [khr_buffer_device_address, ext_buffer_device_address],
|
device_extensions: [khr_buffer_device_address, ext_buffer_device_address],
|
||||||
},
|
},
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// TODO: document
|
// TODO: document
|
||||||
video_decode_src = VIDEO_DECODE_SRC_KHR {
|
VIDEO_DECODE_SRC = VIDEO_DECODE_SRC_KHR {
|
||||||
device_extensions: [khr_video_decode_queue],
|
device_extensions: [khr_video_decode_queue],
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: document
|
// TODO: document
|
||||||
video_decode_dst = VIDEO_DECODE_DST_KHR {
|
VIDEO_DECODE_DST = VIDEO_DECODE_DST_KHR {
|
||||||
device_extensions: [khr_video_decode_queue],
|
device_extensions: [khr_video_decode_queue],
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: document
|
// TODO: document
|
||||||
transform_feedback_buffer = TRANSFORM_FEEDBACK_BUFFER_EXT {
|
TRANSFORM_FEEDBACK_BUFFER = TRANSFORM_FEEDBACK_BUFFER_EXT {
|
||||||
device_extensions: [ext_transform_feedback],
|
device_extensions: [ext_transform_feedback],
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: document
|
// TODO: document
|
||||||
transform_feedback_counter_buffer = TRANSFORM_FEEDBACK_COUNTER_BUFFER_EXT {
|
TRANSFORM_FEEDBACK_COUNTER_BUFFER = TRANSFORM_FEEDBACK_COUNTER_BUFFER_EXT {
|
||||||
device_extensions: [ext_transform_feedback],
|
device_extensions: [ext_transform_feedback],
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: document
|
// TODO: document
|
||||||
conditional_rendering = CONDITIONAL_RENDERING_EXT {
|
CONDITIONAL_RENDERING = CONDITIONAL_RENDERING_EXT {
|
||||||
device_extensions: [ext_conditional_rendering],
|
device_extensions: [ext_conditional_rendering],
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: document
|
// TODO: document
|
||||||
acceleration_structure_build_input_read_only = ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_KHR {
|
ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_KHR = ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_KHR {
|
||||||
device_extensions: [khr_acceleration_structure],
|
device_extensions: [khr_acceleration_structure],
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: document
|
// TODO: document
|
||||||
acceleration_structure_storage = ACCELERATION_STRUCTURE_STORAGE_KHR {
|
ACCELERATION_STRUCTURE_STORAGE = ACCELERATION_STRUCTURE_STORAGE_KHR {
|
||||||
device_extensions: [khr_acceleration_structure],
|
device_extensions: [khr_acceleration_structure],
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: document
|
// TODO: document
|
||||||
shader_binding_table = SHADER_BINDING_TABLE_KHR {
|
SHADER_BINDING_TABLE = SHADER_BINDING_TABLE_KHR {
|
||||||
device_extensions: [khr_ray_tracing_pipeline, nv_ray_tracing],
|
device_extensions: [khr_ray_tracing_pipeline, nv_ray_tracing],
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: document
|
// TODO: document
|
||||||
video_encode_dst = VIDEO_ENCODE_DST_KHR {
|
VIDEO_ENCODE_DST = VIDEO_ENCODE_DST_KHR {
|
||||||
device_extensions: [khr_video_encode_queue],
|
device_extensions: [khr_video_encode_queue],
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: document
|
// TODO: document
|
||||||
video_encode_src = VIDEO_ENCODE_SRC_KHR {
|
VIDEO_ENCODE_SRC = VIDEO_ENCODE_SRC_KHR {
|
||||||
device_extensions: [khr_video_encode_queue],
|
device_extensions: [khr_video_encode_queue],
|
||||||
},
|
},
|
||||||
*/
|
*/
|
||||||
|
@ -26,15 +26,10 @@
|
|||||||
//!
|
//!
|
||||||
//! # let queue: Arc<vulkano::device::Queue> = return;
|
//! # let queue: Arc<vulkano::device::Queue> = return;
|
||||||
//! # let memory_allocator: vulkano::memory::allocator::StandardMemoryAllocator = return;
|
//! # let memory_allocator: vulkano::memory::allocator::StandardMemoryAllocator = return;
|
||||||
//! let usage = BufferUsage {
|
|
||||||
//! storage_texel_buffer: true,
|
|
||||||
//! ..BufferUsage::empty()
|
|
||||||
//! };
|
|
||||||
//!
|
|
||||||
//! let buffer = DeviceLocalBuffer::<[u32]>::array(
|
//! let buffer = DeviceLocalBuffer::<[u32]>::array(
|
||||||
//! &memory_allocator,
|
//! &memory_allocator,
|
||||||
//! 128,
|
//! 128,
|
||||||
//! usage,
|
//! BufferUsage::STORAGE_TEXEL_BUFFER,
|
||||||
//! [queue.queue_family_index()],
|
//! [queue.queue_family_index()],
|
||||||
//! )
|
//! )
|
||||||
//! .unwrap();
|
//! .unwrap();
|
||||||
@ -48,7 +43,7 @@
|
|||||||
//! .unwrap();
|
//! .unwrap();
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
use super::{BufferAccess, BufferAccessObject, BufferInner};
|
use super::{BufferAccess, BufferAccessObject, BufferInner, BufferUsage};
|
||||||
use crate::{
|
use crate::{
|
||||||
device::{Device, DeviceOwned},
|
device::{Device, DeviceOwned},
|
||||||
format::{Format, FormatFeatures},
|
format::{Format, FormatFeatures},
|
||||||
@ -107,7 +102,9 @@ where
|
|||||||
format.validate_device(device)?;
|
format.validate_device(device)?;
|
||||||
|
|
||||||
// VUID-VkBufferViewCreateInfo-buffer-00932
|
// VUID-VkBufferViewCreateInfo-buffer-00932
|
||||||
if !(inner_buffer.usage().uniform_texel_buffer || inner_buffer.usage().storage_texel_buffer)
|
if !inner_buffer
|
||||||
|
.usage()
|
||||||
|
.intersects(BufferUsage::UNIFORM_TEXEL_BUFFER | BufferUsage::STORAGE_TEXEL_BUFFER)
|
||||||
{
|
{
|
||||||
return Err(BufferViewCreationError::BufferMissingUsage);
|
return Err(BufferViewCreationError::BufferMissingUsage);
|
||||||
}
|
}
|
||||||
@ -121,12 +118,20 @@ where
|
|||||||
};
|
};
|
||||||
|
|
||||||
// VUID-VkBufferViewCreateInfo-buffer-00933
|
// VUID-VkBufferViewCreateInfo-buffer-00933
|
||||||
if inner_buffer.usage().uniform_texel_buffer && !format_features.uniform_texel_buffer {
|
if inner_buffer
|
||||||
|
.usage()
|
||||||
|
.intersects(BufferUsage::UNIFORM_TEXEL_BUFFER)
|
||||||
|
&& !format_features.intersects(FormatFeatures::UNIFORM_TEXEL_BUFFER)
|
||||||
|
{
|
||||||
return Err(BufferViewCreationError::UnsupportedFormat);
|
return Err(BufferViewCreationError::UnsupportedFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
// VUID-VkBufferViewCreateInfo-buffer-00934
|
// VUID-VkBufferViewCreateInfo-buffer-00934
|
||||||
if inner_buffer.usage().storage_texel_buffer && !format_features.storage_texel_buffer {
|
if inner_buffer
|
||||||
|
.usage()
|
||||||
|
.intersects(BufferUsage::STORAGE_TEXEL_BUFFER)
|
||||||
|
&& !format_features.intersects(FormatFeatures::STORAGE_TEXEL_BUFFER)
|
||||||
|
{
|
||||||
return Err(BufferViewCreationError::UnsupportedFormat);
|
return Err(BufferViewCreationError::UnsupportedFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,7 +161,10 @@ where
|
|||||||
block_size
|
block_size
|
||||||
};
|
};
|
||||||
|
|
||||||
if inner_buffer.usage().storage_texel_buffer {
|
if inner_buffer
|
||||||
|
.usage()
|
||||||
|
.intersects(BufferUsage::STORAGE_TEXEL_BUFFER)
|
||||||
|
{
|
||||||
let mut required_alignment = properties
|
let mut required_alignment = properties
|
||||||
.storage_texel_buffer_offset_alignment_bytes
|
.storage_texel_buffer_offset_alignment_bytes
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -177,7 +185,10 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if inner_buffer.usage().uniform_texel_buffer {
|
if inner_buffer
|
||||||
|
.usage()
|
||||||
|
.intersects(BufferUsage::UNIFORM_TEXEL_BUFFER)
|
||||||
|
{
|
||||||
let mut required_alignment = properties
|
let mut required_alignment = properties
|
||||||
.uniform_texel_buffer_offset_alignment_bytes
|
.uniform_texel_buffer_offset_alignment_bytes
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -416,7 +427,7 @@ pub unsafe trait BufferViewAbstract:
|
|||||||
fn format(&self) -> Option<Format>;
|
fn format(&self) -> Option<Format>;
|
||||||
|
|
||||||
/// Returns the features supported by the buffer view's format.
|
/// Returns the features supported by the buffer view's format.
|
||||||
fn format_features(&self) -> &FormatFeatures;
|
fn format_features(&self) -> FormatFeatures;
|
||||||
|
|
||||||
/// Returns the byte range of the wrapped buffer that this view exposes.
|
/// Returns the byte range of the wrapped buffer that this view exposes.
|
||||||
fn range(&self) -> Range<DeviceSize>;
|
fn range(&self) -> Range<DeviceSize>;
|
||||||
@ -435,8 +446,8 @@ where
|
|||||||
self.format
|
self.format
|
||||||
}
|
}
|
||||||
|
|
||||||
fn format_features(&self) -> &FormatFeatures {
|
fn format_features(&self) -> FormatFeatures {
|
||||||
&self.format_features
|
self.format_features
|
||||||
}
|
}
|
||||||
|
|
||||||
fn range(&self) -> Range<DeviceSize> {
|
fn range(&self) -> Range<DeviceSize> {
|
||||||
@ -475,10 +486,7 @@ mod tests {
|
|||||||
let (device, queue) = gfx_dev_and_queue!();
|
let (device, queue) = gfx_dev_and_queue!();
|
||||||
let memory_allocator = StandardMemoryAllocator::new_default(device);
|
let memory_allocator = StandardMemoryAllocator::new_default(device);
|
||||||
|
|
||||||
let usage = BufferUsage {
|
let usage = BufferUsage::UNIFORM_TEXEL_BUFFER;
|
||||||
uniform_texel_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
};
|
|
||||||
|
|
||||||
let buffer = DeviceLocalBuffer::<[[u8; 4]]>::array(
|
let buffer = DeviceLocalBuffer::<[[u8; 4]]>::array(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
@ -503,10 +511,7 @@ mod tests {
|
|||||||
let (device, queue) = gfx_dev_and_queue!();
|
let (device, queue) = gfx_dev_and_queue!();
|
||||||
let memory_allocator = StandardMemoryAllocator::new_default(device);
|
let memory_allocator = StandardMemoryAllocator::new_default(device);
|
||||||
|
|
||||||
let usage = BufferUsage {
|
let usage = BufferUsage::STORAGE_TEXEL_BUFFER;
|
||||||
storage_texel_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
};
|
|
||||||
|
|
||||||
let buffer = DeviceLocalBuffer::<[[u8; 4]]>::array(
|
let buffer = DeviceLocalBuffer::<[[u8; 4]]>::array(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
@ -531,10 +536,7 @@ mod tests {
|
|||||||
let (device, queue) = gfx_dev_and_queue!();
|
let (device, queue) = gfx_dev_and_queue!();
|
||||||
let memory_allocator = StandardMemoryAllocator::new_default(device);
|
let memory_allocator = StandardMemoryAllocator::new_default(device);
|
||||||
|
|
||||||
let usage = BufferUsage {
|
let usage = BufferUsage::STORAGE_TEXEL_BUFFER;
|
||||||
storage_texel_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
};
|
|
||||||
|
|
||||||
let buffer = DeviceLocalBuffer::<[u32]>::array(
|
let buffer = DeviceLocalBuffer::<[u32]>::array(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
@ -562,10 +564,7 @@ mod tests {
|
|||||||
let buffer = DeviceLocalBuffer::<[[u8; 4]]>::array(
|
let buffer = DeviceLocalBuffer::<[[u8; 4]]>::array(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
128,
|
128,
|
||||||
BufferUsage {
|
BufferUsage::TRANSFER_DST, // Dummy value
|
||||||
transfer_dst: true, // Dummy value
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
[queue.queue_family_index()],
|
[queue.queue_family_index()],
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -587,11 +586,7 @@ mod tests {
|
|||||||
let (device, queue) = gfx_dev_and_queue!();
|
let (device, queue) = gfx_dev_and_queue!();
|
||||||
let memory_allocator = StandardMemoryAllocator::new_default(device);
|
let memory_allocator = StandardMemoryAllocator::new_default(device);
|
||||||
|
|
||||||
let usage = BufferUsage {
|
let usage = BufferUsage::UNIFORM_TEXEL_BUFFER | BufferUsage::STORAGE_TEXEL_BUFFER;
|
||||||
uniform_texel_buffer: true,
|
|
||||||
storage_texel_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
};
|
|
||||||
|
|
||||||
let buffer = DeviceLocalBuffer::<[[f64; 4]]>::array(
|
let buffer = DeviceLocalBuffer::<[[f64; 4]]>::array(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
|
@ -23,8 +23,8 @@ use crate::{
|
|||||||
buffer::{sys::Buffer, BufferAccess},
|
buffer::{sys::Buffer, BufferAccess},
|
||||||
command_buffer::CommandBufferInheritanceRenderingInfo,
|
command_buffer::CommandBufferInheritanceRenderingInfo,
|
||||||
device::{Device, DeviceOwned, Queue, QueueFamilyProperties},
|
device::{Device, DeviceOwned, Queue, QueueFamilyProperties},
|
||||||
format::Format,
|
format::{Format, FormatFeatures},
|
||||||
image::{sys::Image, ImageAccess, ImageLayout, ImageSubresourceRange},
|
image::{sys::Image, ImageAccess, ImageAspects, ImageLayout, ImageSubresourceRange},
|
||||||
query::{QueryControlFlags, QueryType},
|
query::{QueryControlFlags, QueryType},
|
||||||
render_pass::{Framebuffer, Subpass},
|
render_pass::{Framebuffer, Subpass},
|
||||||
sync::{AccessCheckError, AccessFlags, PipelineMemoryAccess, PipelineStages},
|
sync::{AccessCheckError, AccessFlags, PipelineMemoryAccess, PipelineStages},
|
||||||
@ -350,7 +350,9 @@ where
|
|||||||
// VUID-VkCommandBufferInheritanceRenderingInfo-multiview-06008
|
// VUID-VkCommandBufferInheritanceRenderingInfo-multiview-06008
|
||||||
if view_mask != 0 && !device.enabled_features().multiview {
|
if view_mask != 0 && !device.enabled_features().multiview {
|
||||||
return Err(CommandBufferBeginError::RequirementNotMet {
|
return Err(CommandBufferBeginError::RequirementNotMet {
|
||||||
required_for: "`inheritance_info.render_pass` is `CommandBufferInheritanceRenderPassType::BeginRendering`, where `view_mask` is not `0`",
|
required_for: "`inheritance_info.render_pass` is \
|
||||||
|
`CommandBufferInheritanceRenderPassType::BeginRendering`, \
|
||||||
|
where `view_mask` is not `0`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["multiview"],
|
features: &["multiview"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -382,7 +384,7 @@ where
|
|||||||
// Use unchecked, because all validation has been done above.
|
// Use unchecked, because all validation has been done above.
|
||||||
if !unsafe { physical_device.format_properties_unchecked(format) }
|
if !unsafe { physical_device.format_properties_unchecked(format) }
|
||||||
.potential_format_features()
|
.potential_format_features()
|
||||||
.color_attachment
|
.intersects(FormatFeatures::COLOR_ATTACHMENT)
|
||||||
{
|
{
|
||||||
return Err(
|
return Err(
|
||||||
CommandBufferBeginError::ColorAttachmentFormatUsageNotSupported {
|
CommandBufferBeginError::ColorAttachmentFormatUsageNotSupported {
|
||||||
@ -397,7 +399,7 @@ where
|
|||||||
format.validate_device(device)?;
|
format.validate_device(device)?;
|
||||||
|
|
||||||
// VUID-VkCommandBufferInheritanceRenderingInfo-depthAttachmentFormat-06540
|
// VUID-VkCommandBufferInheritanceRenderingInfo-depthAttachmentFormat-06540
|
||||||
if !format.aspects().depth {
|
if !format.aspects().intersects(ImageAspects::DEPTH) {
|
||||||
return Err(
|
return Err(
|
||||||
CommandBufferBeginError::DepthAttachmentFormatUsageNotSupported,
|
CommandBufferBeginError::DepthAttachmentFormatUsageNotSupported,
|
||||||
);
|
);
|
||||||
@ -407,7 +409,7 @@ where
|
|||||||
// Use unchecked, because all validation has been done above.
|
// Use unchecked, because all validation has been done above.
|
||||||
if !unsafe { physical_device.format_properties_unchecked(format) }
|
if !unsafe { physical_device.format_properties_unchecked(format) }
|
||||||
.potential_format_features()
|
.potential_format_features()
|
||||||
.depth_stencil_attachment
|
.intersects(FormatFeatures::DEPTH_STENCIL_ATTACHMENT)
|
||||||
{
|
{
|
||||||
return Err(
|
return Err(
|
||||||
CommandBufferBeginError::DepthAttachmentFormatUsageNotSupported,
|
CommandBufferBeginError::DepthAttachmentFormatUsageNotSupported,
|
||||||
@ -420,7 +422,7 @@ where
|
|||||||
format.validate_device(device)?;
|
format.validate_device(device)?;
|
||||||
|
|
||||||
// VUID-VkCommandBufferInheritanceRenderingInfo-stencilAttachmentFormat-06541
|
// VUID-VkCommandBufferInheritanceRenderingInfo-stencilAttachmentFormat-06541
|
||||||
if !format.aspects().stencil {
|
if !format.aspects().intersects(ImageAspects::STENCIL) {
|
||||||
return Err(
|
return Err(
|
||||||
CommandBufferBeginError::StencilAttachmentFormatUsageNotSupported,
|
CommandBufferBeginError::StencilAttachmentFormatUsageNotSupported,
|
||||||
);
|
);
|
||||||
@ -430,7 +432,7 @@ where
|
|||||||
// Use unchecked, because all validation has been done above.
|
// Use unchecked, because all validation has been done above.
|
||||||
if !unsafe { physical_device.format_properties_unchecked(format) }
|
if !unsafe { physical_device.format_properties_unchecked(format) }
|
||||||
.potential_format_features()
|
.potential_format_features()
|
||||||
.depth_stencil_attachment
|
.intersects(FormatFeatures::DEPTH_STENCIL_ATTACHMENT)
|
||||||
{
|
{
|
||||||
return Err(
|
return Err(
|
||||||
CommandBufferBeginError::StencilAttachmentFormatUsageNotSupported,
|
CommandBufferBeginError::StencilAttachmentFormatUsageNotSupported,
|
||||||
@ -472,10 +474,13 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VUID-vkBeginCommandBuffer-commandBuffer-00052
|
// VUID-vkBeginCommandBuffer-commandBuffer-00052
|
||||||
if control_flags.precise && !device.enabled_features().occlusion_query_precise {
|
if control_flags.intersects(QueryControlFlags::PRECISE)
|
||||||
|
&& !device.enabled_features().occlusion_query_precise
|
||||||
|
{
|
||||||
return Err(CommandBufferBeginError::RequirementNotMet {
|
return Err(CommandBufferBeginError::RequirementNotMet {
|
||||||
required_for:
|
required_for: "`inheritance_info.occlusion_query` is \
|
||||||
"`inheritance_info.occlusion_query` is `Some(control_flags)`, where `control_flags.precise` is set",
|
`Some(control_flags)`, where `control_flags` contains \
|
||||||
|
`QueryControlFlags::PRECISE`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["occlusion_query_precise"],
|
features: &["occlusion_query_precise"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -948,10 +953,7 @@ mod tests {
|
|||||||
|
|
||||||
let source = CpuAccessibleBuffer::from_iter(
|
let source = CpuAccessibleBuffer::from_iter(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::TRANSFER_SRC,
|
||||||
transfer_src: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
true,
|
true,
|
||||||
[1_u32, 2].iter().copied(),
|
[1_u32, 2].iter().copied(),
|
||||||
)
|
)
|
||||||
@ -959,10 +961,7 @@ mod tests {
|
|||||||
|
|
||||||
let destination = CpuAccessibleBuffer::from_iter(
|
let destination = CpuAccessibleBuffer::from_iter(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::TRANSFER_DST,
|
||||||
transfer_dst: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
true,
|
true,
|
||||||
[0_u32, 10, 20, 3, 4].iter().copied(),
|
[0_u32, 10, 20, 3, 4].iter().copied(),
|
||||||
)
|
)
|
||||||
@ -1083,11 +1082,7 @@ mod tests {
|
|||||||
let memory_allocator = StandardMemoryAllocator::new_default(device.clone());
|
let memory_allocator = StandardMemoryAllocator::new_default(device.clone());
|
||||||
let source = CpuAccessibleBuffer::from_iter(
|
let source = CpuAccessibleBuffer::from_iter(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::TRANSFER_SRC | BufferUsage::TRANSFER_DST,
|
||||||
transfer_src: true,
|
|
||||||
transfer_dst: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
true,
|
true,
|
||||||
[0_u32, 1, 2, 3].iter().copied(),
|
[0_u32, 1, 2, 3].iter().copied(),
|
||||||
)
|
)
|
||||||
@ -1135,11 +1130,7 @@ mod tests {
|
|||||||
let memory_allocator = StandardMemoryAllocator::new_default(device.clone());
|
let memory_allocator = StandardMemoryAllocator::new_default(device.clone());
|
||||||
let source = CpuAccessibleBuffer::from_iter(
|
let source = CpuAccessibleBuffer::from_iter(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::TRANSFER_SRC | BufferUsage::TRANSFER_DST,
|
||||||
transfer_src: true,
|
|
||||||
transfer_dst: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
true,
|
true,
|
||||||
[0_u32, 1, 2, 3].iter().copied(),
|
[0_u32, 1, 2, 3].iter().copied(),
|
||||||
)
|
)
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
// according to those terms.
|
// according to those terms.
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
buffer::{BufferAccess, BufferContents, TypedBufferAccess},
|
buffer::{BufferAccess, BufferContents, BufferUsage, TypedBufferAccess},
|
||||||
command_buffer::{
|
command_buffer::{
|
||||||
allocator::CommandBufferAllocator,
|
allocator::CommandBufferAllocator,
|
||||||
auto::RenderPassStateType,
|
auto::RenderPassStateType,
|
||||||
@ -21,7 +21,7 @@ use crate::{
|
|||||||
DescriptorSetUpdateError, DescriptorSetWithOffsets, DescriptorSetsCollection,
|
DescriptorSetUpdateError, DescriptorSetWithOffsets, DescriptorSetsCollection,
|
||||||
DescriptorWriteInfo, WriteDescriptorSet,
|
DescriptorWriteInfo, WriteDescriptorSet,
|
||||||
},
|
},
|
||||||
device::DeviceOwned,
|
device::{DeviceOwned, QueueFlags},
|
||||||
pipeline::{
|
pipeline::{
|
||||||
graphics::{
|
graphics::{
|
||||||
input_assembly::{Index, IndexType},
|
input_assembly::{Index, IndexType},
|
||||||
@ -104,12 +104,18 @@ where
|
|||||||
// VUID-vkCmdBindDescriptorSets-pipelineBindPoint-00361
|
// VUID-vkCmdBindDescriptorSets-pipelineBindPoint-00361
|
||||||
match pipeline_bind_point {
|
match pipeline_bind_point {
|
||||||
PipelineBindPoint::Compute => {
|
PipelineBindPoint::Compute => {
|
||||||
if !queue_family_properties.queue_flags.compute {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::COMPUTE)
|
||||||
|
{
|
||||||
return Err(BindPushError::NotSupportedByQueueFamily);
|
return Err(BindPushError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PipelineBindPoint::Graphics => {
|
PipelineBindPoint::Graphics => {
|
||||||
if !queue_family_properties.queue_flags.graphics {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS)
|
||||||
|
{
|
||||||
return Err(BindPushError::NotSupportedByQueueFamily);
|
return Err(BindPushError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -152,11 +158,12 @@ where
|
|||||||
///
|
///
|
||||||
/// - Panics if the queue family of the command buffer does not support graphics operations.
|
/// - Panics if the queue family of the command buffer does not support graphics operations.
|
||||||
/// - Panics if `self` and `index_buffer` do not belong to the same device.
|
/// - Panics if `self` and `index_buffer` do not belong to the same device.
|
||||||
/// - Panics if `index_buffer` does not have the
|
/// - Panics if `index_buffer` does not have the [`BufferUsage::INDEX_BUFFER`] usage enabled.
|
||||||
/// [`index_buffer`](crate::buffer::BufferUsage::index_buffer) usage enabled.
|
/// - If the index buffer contains `u8` indices, panics if the [`index_type_uint8`] feature is
|
||||||
/// - If the index buffer contains `u8` indices, panics if the
|
/// not enabled on the device.
|
||||||
/// [`index_type_uint8`](crate::device::Features::index_type_uint8) feature is not
|
///
|
||||||
/// enabled on the device.
|
/// [`BufferUsage::INDEX_BUFFER`]: crate::buffer::BufferUsage::INDEX_BUFFER
|
||||||
|
/// [`index_type_uint8`]: crate::device::Features::index_type_uint8
|
||||||
pub fn bind_index_buffer<Ib, I>(&mut self, index_buffer: Arc<Ib>) -> &mut Self
|
pub fn bind_index_buffer<Ib, I>(&mut self, index_buffer: Arc<Ib>) -> &mut Self
|
||||||
where
|
where
|
||||||
Ib: TypedBufferAccess<Content = [I]> + 'static,
|
Ib: TypedBufferAccess<Content = [I]> + 'static,
|
||||||
@ -180,7 +187,10 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdBindIndexBuffer-commandBuffer-cmdpool
|
// VUID-vkCmdBindIndexBuffer-commandBuffer-cmdpool
|
||||||
if !queue_family_properties.queue_flags.graphics {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS)
|
||||||
|
{
|
||||||
return Err(BindPushError::NotSupportedByQueueFamily);
|
return Err(BindPushError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,7 +198,7 @@ where
|
|||||||
assert_eq!(self.device(), index_buffer.device());
|
assert_eq!(self.device(), index_buffer.device());
|
||||||
|
|
||||||
// VUID-vkCmdBindIndexBuffer-buffer-00433
|
// VUID-vkCmdBindIndexBuffer-buffer-00433
|
||||||
if !index_buffer.usage().index_buffer {
|
if !index_buffer.usage().intersects(BufferUsage::INDEX_BUFFER) {
|
||||||
return Err(BindPushError::IndexBufferMissingUsage);
|
return Err(BindPushError::IndexBufferMissingUsage);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,7 +242,10 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdBindPipeline-pipelineBindPoint-00777
|
// VUID-vkCmdBindPipeline-pipelineBindPoint-00777
|
||||||
if !queue_family_properties.queue_flags.compute {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::COMPUTE)
|
||||||
|
{
|
||||||
return Err(BindPushError::NotSupportedByQueueFamily);
|
return Err(BindPushError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,7 +278,10 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdBindPipeline-pipelineBindPoint-00778
|
// VUID-vkCmdBindPipeline-pipelineBindPoint-00778
|
||||||
if !queue_family_properties.queue_flags.graphics {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS)
|
||||||
|
{
|
||||||
return Err(BindPushError::NotSupportedByQueueFamily);
|
return Err(BindPushError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -322,11 +338,13 @@ where
|
|||||||
///
|
///
|
||||||
/// - Panics if the queue family of the command buffer does not support graphics operations.
|
/// - Panics if the queue family of the command buffer does not support graphics operations.
|
||||||
/// - Panics if the highest vertex buffer binding being bound is greater than the
|
/// - Panics if the highest vertex buffer binding being bound is greater than the
|
||||||
/// [`max_vertex_input_bindings`](crate::device::Properties::max_vertex_input_bindings)
|
/// [`max_vertex_input_bindings`] device property.
|
||||||
// device property.
|
|
||||||
/// - Panics if `self` and any element of `vertex_buffers` do not belong to the same device.
|
/// - Panics if `self` and any element of `vertex_buffers` do not belong to the same device.
|
||||||
/// - Panics if any element of `vertex_buffers` does not have the
|
/// - Panics if any element of `vertex_buffers` does not have the
|
||||||
/// [`vertex_buffer`](crate::buffer::BufferUsage::vertex_buffer) usage enabled.
|
/// [`BufferUsage::VERTEX_BUFFER`] usage enabled.
|
||||||
|
///
|
||||||
|
/// [`max_vertex_input_bindings`]: crate::device::Properties::max_vertex_input_bindings
|
||||||
|
/// [`BufferUsage::VERTEX_BUFFER`]: crate::buffer::BufferUsage::VERTEX_BUFFER
|
||||||
pub fn bind_vertex_buffers(
|
pub fn bind_vertex_buffers(
|
||||||
&mut self,
|
&mut self,
|
||||||
first_binding: u32,
|
first_binding: u32,
|
||||||
@ -355,7 +373,10 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdBindVertexBuffers-commandBuffer-cmdpool
|
// VUID-vkCmdBindVertexBuffers-commandBuffer-cmdpool
|
||||||
if !queue_family_properties.queue_flags.graphics {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS)
|
||||||
|
{
|
||||||
return Err(BindPushError::NotSupportedByQueueFamily);
|
return Err(BindPushError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -383,7 +404,7 @@ where
|
|||||||
assert_eq!(self.device(), buffer.device());
|
assert_eq!(self.device(), buffer.device());
|
||||||
|
|
||||||
// VUID-vkCmdBindVertexBuffers-pBuffers-00627
|
// VUID-vkCmdBindVertexBuffers-pBuffers-00627
|
||||||
if !buffer.usage().vertex_buffer {
|
if !buffer.usage().intersects(BufferUsage::VERTEX_BUFFER) {
|
||||||
return Err(BindPushError::VertexBufferMissingUsage);
|
return Err(BindPushError::VertexBufferMissingUsage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -554,7 +575,7 @@ where
|
|||||||
) -> Result<(), BindPushError> {
|
) -> Result<(), BindPushError> {
|
||||||
if !self.device().enabled_extensions().khr_push_descriptor {
|
if !self.device().enabled_extensions().khr_push_descriptor {
|
||||||
return Err(BindPushError::RequirementNotMet {
|
return Err(BindPushError::RequirementNotMet {
|
||||||
required_for: "`push_descriptor_set`",
|
required_for: "`AutoCommandBufferBuilder::push_descriptor_set`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
device_extensions: &["khr_push_descriptor"],
|
device_extensions: &["khr_push_descriptor"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -571,12 +592,18 @@ where
|
|||||||
// VUID-vkCmdPushDescriptorSetKHR-pipelineBindPoint-00363
|
// VUID-vkCmdPushDescriptorSetKHR-pipelineBindPoint-00363
|
||||||
match pipeline_bind_point {
|
match pipeline_bind_point {
|
||||||
PipelineBindPoint::Compute => {
|
PipelineBindPoint::Compute => {
|
||||||
if !queue_family_properties.queue_flags.compute {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::COMPUTE)
|
||||||
|
{
|
||||||
return Err(BindPushError::NotSupportedByQueueFamily);
|
return Err(BindPushError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PipelineBindPoint::Graphics => {
|
PipelineBindPoint::Graphics => {
|
||||||
if !queue_family_properties.queue_flags.graphics {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS)
|
||||||
|
{
|
||||||
return Err(BindPushError::NotSupportedByQueueFamily);
|
return Err(BindPushError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -999,7 +1026,7 @@ impl UnsafeCommandBufferBuilder {
|
|||||||
|
|
||||||
let inner = buffer.inner();
|
let inner = buffer.inner();
|
||||||
debug_assert!(inner.offset < inner.buffer.size());
|
debug_assert!(inner.offset < inner.buffer.size());
|
||||||
debug_assert!(inner.buffer.usage().index_buffer);
|
debug_assert!(inner.buffer.usage().intersects(BufferUsage::INDEX_BUFFER));
|
||||||
|
|
||||||
(fns.v1_0.cmd_bind_index_buffer)(
|
(fns.v1_0.cmd_bind_index_buffer)(
|
||||||
self.handle,
|
self.handle,
|
||||||
@ -1184,7 +1211,7 @@ impl UnsafeCommandBufferBuilderBindVertexBuffer {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn add(&mut self, buffer: &dyn BufferAccess) {
|
pub fn add(&mut self, buffer: &dyn BufferAccess) {
|
||||||
let inner = buffer.inner();
|
let inner = buffer.inner();
|
||||||
debug_assert!(inner.buffer.usage().vertex_buffer);
|
debug_assert!(inner.buffer.usage().intersects(BufferUsage::VERTEX_BUFFER));
|
||||||
self.raw_buffers.push(inner.buffer.handle());
|
self.raw_buffers.push(inner.buffer.handle());
|
||||||
self.offsets.push(inner.offset);
|
self.offsets.push(inner.offset);
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ use crate::{
|
|||||||
sys::UnsafeCommandBufferBuilder,
|
sys::UnsafeCommandBufferBuilder,
|
||||||
AutoCommandBufferBuilder,
|
AutoCommandBufferBuilder,
|
||||||
},
|
},
|
||||||
device::DeviceOwned,
|
device::{DeviceOwned, QueueFlags},
|
||||||
instance::debug::DebugUtilsLabel,
|
instance::debug::DebugUtilsLabel,
|
||||||
RequiresOneOf,
|
RequiresOneOf,
|
||||||
};
|
};
|
||||||
@ -26,9 +26,9 @@ use std::{
|
|||||||
|
|
||||||
/// # Commands for debugging.
|
/// # Commands for debugging.
|
||||||
///
|
///
|
||||||
/// These commands all require the
|
/// These commands all require the [`ext_debug_utils`] extension to be enabled on the instance.
|
||||||
/// [`ext_debug_utils`](crate::instance::InstanceExtensions::ext_debug_utils) to be enabled on the
|
///
|
||||||
/// instance.
|
/// [`ext_debug_utils`]: crate::instance::InstanceExtensions::ext_debug_utils
|
||||||
impl<L, A> AutoCommandBufferBuilder<L, A>
|
impl<L, A> AutoCommandBufferBuilder<L, A>
|
||||||
where
|
where
|
||||||
A: CommandBufferAllocator,
|
A: CommandBufferAllocator,
|
||||||
@ -58,7 +58,7 @@ where
|
|||||||
.ext_debug_utils
|
.ext_debug_utils
|
||||||
{
|
{
|
||||||
return Err(DebugUtilsError::RequirementNotMet {
|
return Err(DebugUtilsError::RequirementNotMet {
|
||||||
required_for: "`begin_debug_utils_label`",
|
required_for: "`AutoCommandBufferBuilder::begin_debug_utils_label`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
instance_extensions: &["ext_debug_utils"],
|
instance_extensions: &["ext_debug_utils"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -69,8 +69,9 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdBeginDebugUtilsLabelEXT-commandBuffer-cmdpool
|
// VUID-vkCmdBeginDebugUtilsLabelEXT-commandBuffer-cmdpool
|
||||||
if !(queue_family_properties.queue_flags.graphics
|
if !queue_family_properties
|
||||||
|| queue_family_properties.queue_flags.compute)
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS | QueueFlags::COMPUTE)
|
||||||
{
|
{
|
||||||
return Err(DebugUtilsError::NotSupportedByQueueFamily);
|
return Err(DebugUtilsError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
@ -101,7 +102,7 @@ where
|
|||||||
.ext_debug_utils
|
.ext_debug_utils
|
||||||
{
|
{
|
||||||
return Err(DebugUtilsError::RequirementNotMet {
|
return Err(DebugUtilsError::RequirementNotMet {
|
||||||
required_for: "`end_debug_utils_label`",
|
required_for: "`AutoCommandBufferBuilder::end_debug_utils_label`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
instance_extensions: &["ext_debug_utils"],
|
instance_extensions: &["ext_debug_utils"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -112,8 +113,9 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdEndDebugUtilsLabelEXT-commandBuffer-cmdpool
|
// VUID-vkCmdEndDebugUtilsLabelEXT-commandBuffer-cmdpool
|
||||||
if !(queue_family_properties.queue_flags.graphics
|
if !queue_family_properties
|
||||||
|| queue_family_properties.queue_flags.compute)
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS | QueueFlags::COMPUTE)
|
||||||
{
|
{
|
||||||
return Err(DebugUtilsError::NotSupportedByQueueFamily);
|
return Err(DebugUtilsError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
@ -152,7 +154,7 @@ where
|
|||||||
.ext_debug_utils
|
.ext_debug_utils
|
||||||
{
|
{
|
||||||
return Err(DebugUtilsError::RequirementNotMet {
|
return Err(DebugUtilsError::RequirementNotMet {
|
||||||
required_for: "`insert_debug_utils_label`",
|
required_for: "`AutoCommandBufferBuilder::insert_debug_utils_label`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
instance_extensions: &["ext_debug_utils"],
|
instance_extensions: &["ext_debug_utils"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -163,8 +165,9 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdInsertDebugUtilsLabelEXT-commandBuffer-cmdpool
|
// VUID-vkCmdInsertDebugUtilsLabelEXT-commandBuffer-cmdpool
|
||||||
if !(queue_family_properties.queue_flags.graphics
|
if !queue_family_properties
|
||||||
|| queue_family_properties.queue_flags.compute)
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS | QueueFlags::COMPUTE)
|
||||||
{
|
{
|
||||||
return Err(DebugUtilsError::NotSupportedByQueueFamily);
|
return Err(DebugUtilsError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ use crate::{
|
|||||||
sys::UnsafeCommandBufferBuilder,
|
sys::UnsafeCommandBufferBuilder,
|
||||||
AutoCommandBufferBuilder,
|
AutoCommandBufferBuilder,
|
||||||
},
|
},
|
||||||
device::DeviceOwned,
|
device::{DeviceOwned, QueueFlags},
|
||||||
pipeline::{
|
pipeline::{
|
||||||
graphics::{
|
graphics::{
|
||||||
color_blend::LogicOp,
|
color_blend::LogicOp,
|
||||||
@ -82,7 +82,10 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdSetBlendConstants-commandBuffer-cmdpool
|
// VUID-vkCmdSetBlendConstants-commandBuffer-cmdpool
|
||||||
if !queue_family_properties.queue_flags.graphics {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS)
|
||||||
|
{
|
||||||
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,14 +128,17 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdSetColorWriteEnableEXT-commandBuffer-cmdpool
|
// VUID-vkCmdSetColorWriteEnableEXT-commandBuffer-cmdpool
|
||||||
if !queue_family_properties.queue_flags.graphics {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS)
|
||||||
|
{
|
||||||
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
// VUID-vkCmdSetColorWriteEnableEXT-None-04803
|
// VUID-vkCmdSetColorWriteEnableEXT-None-04803
|
||||||
if !self.device().enabled_features().color_write_enable {
|
if !self.device().enabled_features().color_write_enable {
|
||||||
return Err(SetDynamicStateError::RequirementNotMet {
|
return Err(SetDynamicStateError::RequirementNotMet {
|
||||||
required_for: "`set_color_write_enable`",
|
required_for: "`AutoCommandBufferBuilder::set_color_write_enable`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
device_extensions: &["ext_color_write_enable"],
|
device_extensions: &["ext_color_write_enable"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -188,7 +194,10 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdSetCullMode-commandBuffer-cmdpool
|
// VUID-vkCmdSetCullMode-commandBuffer-cmdpool
|
||||||
if !queue_family_properties.queue_flags.graphics {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS)
|
||||||
|
{
|
||||||
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,7 +206,7 @@ where
|
|||||||
|| self.device().enabled_features().extended_dynamic_state)
|
|| self.device().enabled_features().extended_dynamic_state)
|
||||||
{
|
{
|
||||||
return Err(SetDynamicStateError::RequirementNotMet {
|
return Err(SetDynamicStateError::RequirementNotMet {
|
||||||
required_for: "`set_cull_mode`",
|
required_for: "`AutoCommandBufferBuilder::set_cull_mode`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
api_version: Some(Version::V1_3),
|
api_version: Some(Version::V1_3),
|
||||||
features: &["extended_dynamic_state"],
|
features: &["extended_dynamic_state"],
|
||||||
@ -245,7 +254,10 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdSetDepthBias-commandBuffer-cmdpool
|
// VUID-vkCmdSetDepthBias-commandBuffer-cmdpool
|
||||||
if !queue_family_properties.queue_flags.graphics {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS)
|
||||||
|
{
|
||||||
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -288,7 +300,10 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdSetDepthBiasEnable-commandBuffer-cmdpool
|
// VUID-vkCmdSetDepthBiasEnable-commandBuffer-cmdpool
|
||||||
if !queue_family_properties.queue_flags.graphics {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS)
|
||||||
|
{
|
||||||
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,7 +312,7 @@ where
|
|||||||
|| self.device().enabled_features().extended_dynamic_state2)
|
|| self.device().enabled_features().extended_dynamic_state2)
|
||||||
{
|
{
|
||||||
return Err(SetDynamicStateError::RequirementNotMet {
|
return Err(SetDynamicStateError::RequirementNotMet {
|
||||||
required_for: "`set_depth_bias_enable`",
|
required_for: "`AutoCommandBufferBuilder::set_depth_bias_enable`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
api_version: Some(Version::V1_3),
|
api_version: Some(Version::V1_3),
|
||||||
features: &["extended_dynamic_state2"],
|
features: &["extended_dynamic_state2"],
|
||||||
@ -338,7 +353,10 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdSetDepthBounds-commandBuffer-cmdpool
|
// VUID-vkCmdSetDepthBounds-commandBuffer-cmdpool
|
||||||
if !queue_family_properties.queue_flags.graphics {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS)
|
||||||
|
{
|
||||||
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -390,7 +408,10 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdSetDepthBoundsTestEnable-commandBuffer-cmdpool
|
// VUID-vkCmdSetDepthBoundsTestEnable-commandBuffer-cmdpool
|
||||||
if !queue_family_properties.queue_flags.graphics {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS)
|
||||||
|
{
|
||||||
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -399,7 +420,7 @@ where
|
|||||||
|| self.device().enabled_features().extended_dynamic_state)
|
|| self.device().enabled_features().extended_dynamic_state)
|
||||||
{
|
{
|
||||||
return Err(SetDynamicStateError::RequirementNotMet {
|
return Err(SetDynamicStateError::RequirementNotMet {
|
||||||
required_for: "`set_depth_bounds_test_enable`",
|
required_for: "`AutoCommandBufferBuilder::set_depth_bounds_test_enable`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
api_version: Some(Version::V1_3),
|
api_version: Some(Version::V1_3),
|
||||||
features: &["extended_dynamic_state"],
|
features: &["extended_dynamic_state"],
|
||||||
@ -442,7 +463,10 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdSetDepthCompareOp-commandBuffer-cmdpool
|
// VUID-vkCmdSetDepthCompareOp-commandBuffer-cmdpool
|
||||||
if !queue_family_properties.queue_flags.graphics {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS)
|
||||||
|
{
|
||||||
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -451,7 +475,7 @@ where
|
|||||||
|| self.device().enabled_features().extended_dynamic_state)
|
|| self.device().enabled_features().extended_dynamic_state)
|
||||||
{
|
{
|
||||||
return Err(SetDynamicStateError::RequirementNotMet {
|
return Err(SetDynamicStateError::RequirementNotMet {
|
||||||
required_for: "`set_depth_compare_op`",
|
required_for: "`AutoCommandBufferBuilder::set_depth_compare_op`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
api_version: Some(Version::V1_3),
|
api_version: Some(Version::V1_3),
|
||||||
features: &["extended_dynamic_state"],
|
features: &["extended_dynamic_state"],
|
||||||
@ -488,7 +512,10 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdSetDepthTestEnable-commandBuffer-cmdpool
|
// VUID-vkCmdSetDepthTestEnable-commandBuffer-cmdpool
|
||||||
if !queue_family_properties.queue_flags.graphics {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS)
|
||||||
|
{
|
||||||
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -497,7 +524,7 @@ where
|
|||||||
|| self.device().enabled_features().extended_dynamic_state)
|
|| self.device().enabled_features().extended_dynamic_state)
|
||||||
{
|
{
|
||||||
return Err(SetDynamicStateError::RequirementNotMet {
|
return Err(SetDynamicStateError::RequirementNotMet {
|
||||||
required_for: "`set_depth_test_enable`",
|
required_for: "`AutoCommandBufferBuilder::set_depth_test_enable`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
api_version: Some(Version::V1_3),
|
api_version: Some(Version::V1_3),
|
||||||
features: &["extended_dynamic_state"],
|
features: &["extended_dynamic_state"],
|
||||||
@ -534,7 +561,10 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdSetDepthWriteEnable-commandBuffer-cmdpool
|
// VUID-vkCmdSetDepthWriteEnable-commandBuffer-cmdpool
|
||||||
if !queue_family_properties.queue_flags.graphics {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS)
|
||||||
|
{
|
||||||
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -543,7 +573,7 @@ where
|
|||||||
|| self.device().enabled_features().extended_dynamic_state)
|
|| self.device().enabled_features().extended_dynamic_state)
|
||||||
{
|
{
|
||||||
return Err(SetDynamicStateError::RequirementNotMet {
|
return Err(SetDynamicStateError::RequirementNotMet {
|
||||||
required_for: "`set_depth_write_enable`",
|
required_for: "`AutoCommandBufferBuilder::set_depth_write_enable`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
api_version: Some(Version::V1_3),
|
api_version: Some(Version::V1_3),
|
||||||
features: &["extended_dynamic_state"],
|
features: &["extended_dynamic_state"],
|
||||||
@ -594,13 +624,16 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdSetDiscardRectangle-commandBuffer-cmdpool
|
// VUID-vkCmdSetDiscardRectangle-commandBuffer-cmdpool
|
||||||
if !queue_family_properties.queue_flags.graphics {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS)
|
||||||
|
{
|
||||||
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.device().enabled_extensions().ext_discard_rectangles {
|
if self.device().enabled_extensions().ext_discard_rectangles {
|
||||||
return Err(SetDynamicStateError::RequirementNotMet {
|
return Err(SetDynamicStateError::RequirementNotMet {
|
||||||
required_for: "`set_discard_rectangle`",
|
required_for: "`AutoCommandBufferBuilder::set_discard_rectangle`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
device_extensions: &["ext_discard_rectangles"],
|
device_extensions: &["ext_discard_rectangles"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -659,7 +692,10 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdSetFrontFace-commandBuffer-cmdpool
|
// VUID-vkCmdSetFrontFace-commandBuffer-cmdpool
|
||||||
if !queue_family_properties.queue_flags.graphics {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS)
|
||||||
|
{
|
||||||
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -668,7 +704,7 @@ where
|
|||||||
|| self.device().enabled_features().extended_dynamic_state)
|
|| self.device().enabled_features().extended_dynamic_state)
|
||||||
{
|
{
|
||||||
return Err(SetDynamicStateError::RequirementNotMet {
|
return Err(SetDynamicStateError::RequirementNotMet {
|
||||||
required_for: "`set_front_face`",
|
required_for: "`AutoCommandBufferBuilder::set_front_face`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
api_version: Some(Version::V1_3),
|
api_version: Some(Version::V1_3),
|
||||||
features: &["extended_dynamic_state"],
|
features: &["extended_dynamic_state"],
|
||||||
@ -709,13 +745,16 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdSetLineStippleEXT-commandBuffer-cmdpool
|
// VUID-vkCmdSetLineStippleEXT-commandBuffer-cmdpool
|
||||||
if !queue_family_properties.queue_flags.graphics {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS)
|
||||||
|
{
|
||||||
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
if !self.device().enabled_extensions().ext_line_rasterization {
|
if !self.device().enabled_extensions().ext_line_rasterization {
|
||||||
return Err(SetDynamicStateError::RequirementNotMet {
|
return Err(SetDynamicStateError::RequirementNotMet {
|
||||||
required_for: "`set_line_stipple`",
|
required_for: "`AutoCommandBufferBuilder::set_line_stipple`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
device_extensions: &["ext_line_rasterization"],
|
device_extensions: &["ext_line_rasterization"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -755,7 +794,10 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdSetLineWidth-commandBuffer-cmdpool
|
// VUID-vkCmdSetLineWidth-commandBuffer-cmdpool
|
||||||
if !queue_family_properties.queue_flags.graphics {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS)
|
||||||
|
{
|
||||||
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -801,7 +843,10 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdSetLogicOpEXT-commandBuffer-cmdpool
|
// VUID-vkCmdSetLogicOpEXT-commandBuffer-cmdpool
|
||||||
if !queue_family_properties.queue_flags.graphics {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS)
|
||||||
|
{
|
||||||
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -812,7 +857,7 @@ where
|
|||||||
.extended_dynamic_state2_logic_op
|
.extended_dynamic_state2_logic_op
|
||||||
{
|
{
|
||||||
return Err(SetDynamicStateError::RequirementNotMet {
|
return Err(SetDynamicStateError::RequirementNotMet {
|
||||||
required_for: "`set_logic_op`",
|
required_for: "`AutoCommandBufferBuilder::set_logic_op`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["extended_dynamic_state2_logic_op"],
|
features: &["extended_dynamic_state2_logic_op"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -852,7 +897,10 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdSetPatchControlPointsEXT-commandBuffer-cmdpool
|
// VUID-vkCmdSetPatchControlPointsEXT-commandBuffer-cmdpool
|
||||||
if !queue_family_properties.queue_flags.graphics {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS)
|
||||||
|
{
|
||||||
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -863,7 +911,7 @@ where
|
|||||||
.extended_dynamic_state2_patch_control_points
|
.extended_dynamic_state2_patch_control_points
|
||||||
{
|
{
|
||||||
return Err(SetDynamicStateError::RequirementNotMet {
|
return Err(SetDynamicStateError::RequirementNotMet {
|
||||||
required_for: "`set_patch_control_points`",
|
required_for: "`AutoCommandBufferBuilder::set_patch_control_points`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["extended_dynamic_state2_patch_control_points"],
|
features: &["extended_dynamic_state2_patch_control_points"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -923,7 +971,10 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdSetPrimitiveRestartEnable-commandBuffer-cmdpool
|
// VUID-vkCmdSetPrimitiveRestartEnable-commandBuffer-cmdpool
|
||||||
if !queue_family_properties.queue_flags.graphics {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS)
|
||||||
|
{
|
||||||
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -932,7 +983,7 @@ where
|
|||||||
|| self.device().enabled_features().extended_dynamic_state2)
|
|| self.device().enabled_features().extended_dynamic_state2)
|
||||||
{
|
{
|
||||||
return Err(SetDynamicStateError::RequirementNotMet {
|
return Err(SetDynamicStateError::RequirementNotMet {
|
||||||
required_for: "`set_primitive_restart_enable`",
|
required_for: "`AutoCommandBufferBuilder::set_primitive_restart_enable`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
api_version: Some(Version::V1_3),
|
api_version: Some(Version::V1_3),
|
||||||
features: &["extended_dynamic_state2"],
|
features: &["extended_dynamic_state2"],
|
||||||
@ -979,7 +1030,10 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdSetPrimitiveTopology-commandBuffer-cmdpool
|
// VUID-vkCmdSetPrimitiveTopology-commandBuffer-cmdpool
|
||||||
if !queue_family_properties.queue_flags.graphics {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS)
|
||||||
|
{
|
||||||
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -988,7 +1042,7 @@ where
|
|||||||
|| self.device().enabled_features().extended_dynamic_state)
|
|| self.device().enabled_features().extended_dynamic_state)
|
||||||
{
|
{
|
||||||
return Err(SetDynamicStateError::RequirementNotMet {
|
return Err(SetDynamicStateError::RequirementNotMet {
|
||||||
required_for: "`set_primitive_topology`",
|
required_for: "`AutoCommandBufferBuilder::set_primitive_topology`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
api_version: Some(Version::V1_3),
|
api_version: Some(Version::V1_3),
|
||||||
features: &["extended_dynamic_state"],
|
features: &["extended_dynamic_state"],
|
||||||
@ -1006,9 +1060,8 @@ where
|
|||||||
&& !self.device().enabled_features().triangle_fans
|
&& !self.device().enabled_features().triangle_fans
|
||||||
{
|
{
|
||||||
return Err(SetDynamicStateError::RequirementNotMet {
|
return Err(SetDynamicStateError::RequirementNotMet {
|
||||||
required_for:
|
required_for: "this device is a portability subset device, and `topology` \
|
||||||
"this device is a portability subset device, and `topology` is \
|
is `PrimitiveTopology::TriangleFan`",
|
||||||
`PrimitiveTopology::TriangleFan`",
|
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["triangle_fans"],
|
features: &["triangle_fans"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -1075,7 +1128,10 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdSetRasterizerDiscardEnable-commandBuffer-cmdpool
|
// VUID-vkCmdSetRasterizerDiscardEnable-commandBuffer-cmdpool
|
||||||
if !queue_family_properties.queue_flags.graphics {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS)
|
||||||
|
{
|
||||||
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1084,7 +1140,7 @@ where
|
|||||||
|| self.device().enabled_features().extended_dynamic_state2)
|
|| self.device().enabled_features().extended_dynamic_state2)
|
||||||
{
|
{
|
||||||
return Err(SetDynamicStateError::RequirementNotMet {
|
return Err(SetDynamicStateError::RequirementNotMet {
|
||||||
required_for: "`set_rasterizer_discard_enable`",
|
required_for: "`AutoCommandBufferBuilder::set_rasterizer_discard_enable`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
api_version: Some(Version::V1_3),
|
api_version: Some(Version::V1_3),
|
||||||
features: &["extended_dynamic_state2"],
|
features: &["extended_dynamic_state2"],
|
||||||
@ -1131,7 +1187,10 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdSetScissor-commandBuffer-cmdpool
|
// VUID-vkCmdSetScissor-commandBuffer-cmdpool
|
||||||
if !queue_family_properties.queue_flags.graphics {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS)
|
||||||
|
{
|
||||||
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1208,7 +1267,10 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdSetScissorWithCount-commandBuffer-cmdpool
|
// VUID-vkCmdSetScissorWithCount-commandBuffer-cmdpool
|
||||||
if !queue_family_properties.queue_flags.graphics {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS)
|
||||||
|
{
|
||||||
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1217,7 +1279,7 @@ where
|
|||||||
|| self.device().enabled_features().extended_dynamic_state)
|
|| self.device().enabled_features().extended_dynamic_state)
|
||||||
{
|
{
|
||||||
return Err(SetDynamicStateError::RequirementNotMet {
|
return Err(SetDynamicStateError::RequirementNotMet {
|
||||||
required_for: "`set_scissor_with_count`",
|
required_for: "`AutoCommandBufferBuilder::set_scissor_with_count`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
api_version: Some(Version::V1_3),
|
api_version: Some(Version::V1_3),
|
||||||
features: &["extended_dynamic_state"],
|
features: &["extended_dynamic_state"],
|
||||||
@ -1282,7 +1344,10 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdSetStencilCompareMask-commandBuffer-cmdpool
|
// VUID-vkCmdSetStencilCompareMask-commandBuffer-cmdpool
|
||||||
if !queue_family_properties.queue_flags.graphics {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS)
|
||||||
|
{
|
||||||
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1345,7 +1410,10 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdSetStencilOp-commandBuffer-cmdpool
|
// VUID-vkCmdSetStencilOp-commandBuffer-cmdpool
|
||||||
if !queue_family_properties.queue_flags.graphics {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS)
|
||||||
|
{
|
||||||
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1354,7 +1422,7 @@ where
|
|||||||
|| self.device().enabled_features().extended_dynamic_state)
|
|| self.device().enabled_features().extended_dynamic_state)
|
||||||
{
|
{
|
||||||
return Err(SetDynamicStateError::RequirementNotMet {
|
return Err(SetDynamicStateError::RequirementNotMet {
|
||||||
required_for: "`set_stencil_op`",
|
required_for: "`AutoCommandBufferBuilder::set_stencil_op`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
api_version: Some(Version::V1_3),
|
api_version: Some(Version::V1_3),
|
||||||
features: &["extended_dynamic_state"],
|
features: &["extended_dynamic_state"],
|
||||||
@ -1396,7 +1464,10 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdSetStencilReference-commandBuffer-cmdpool
|
// VUID-vkCmdSetStencilReference-commandBuffer-cmdpool
|
||||||
if !queue_family_properties.queue_flags.graphics {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS)
|
||||||
|
{
|
||||||
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1428,7 +1499,10 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdSetStencilTestEnable-commandBuffer-cmdpool
|
// VUID-vkCmdSetStencilTestEnable-commandBuffer-cmdpool
|
||||||
if !queue_family_properties.queue_flags.graphics {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS)
|
||||||
|
{
|
||||||
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1437,7 +1511,7 @@ where
|
|||||||
|| self.device().enabled_features().extended_dynamic_state)
|
|| self.device().enabled_features().extended_dynamic_state)
|
||||||
{
|
{
|
||||||
return Err(SetDynamicStateError::RequirementNotMet {
|
return Err(SetDynamicStateError::RequirementNotMet {
|
||||||
required_for: "`set_stencil_test_enable`",
|
required_for: "`AutoCommandBufferBuilder::set_stencil_test_enable`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
api_version: Some(Version::V1_3),
|
api_version: Some(Version::V1_3),
|
||||||
features: &["extended_dynamic_state"],
|
features: &["extended_dynamic_state"],
|
||||||
@ -1479,7 +1553,10 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdSetStencilWriteMask-commandBuffer-cmdpool
|
// VUID-vkCmdSetStencilWriteMask-commandBuffer-cmdpool
|
||||||
if !queue_family_properties.queue_flags.graphics {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS)
|
||||||
|
{
|
||||||
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1522,7 +1599,10 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdSetViewport-commandBuffer-cmdpool
|
// VUID-vkCmdSetViewport-commandBuffer-cmdpool
|
||||||
if !queue_family_properties.queue_flags.graphics {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS)
|
||||||
|
{
|
||||||
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1599,7 +1679,10 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdSetViewportWithCount-commandBuffer-cmdpool
|
// VUID-vkCmdSetViewportWithCount-commandBuffer-cmdpool
|
||||||
if !queue_family_properties.queue_flags.graphics {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS)
|
||||||
|
{
|
||||||
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
return Err(SetDynamicStateError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1608,7 +1691,7 @@ where
|
|||||||
|| self.device().enabled_features().extended_dynamic_state)
|
|| self.device().enabled_features().extended_dynamic_state)
|
||||||
{
|
{
|
||||||
return Err(SetDynamicStateError::RequirementNotMet {
|
return Err(SetDynamicStateError::RequirementNotMet {
|
||||||
required_for: "`set_viewport_with_count`",
|
required_for: "`AutoCommandBufferBuilder::set_viewport_with_count`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
api_version: Some(Version::V1_3),
|
api_version: Some(Version::V1_3),
|
||||||
features: &["extended_dynamic_state"],
|
features: &["extended_dynamic_state"],
|
||||||
|
@ -14,11 +14,11 @@ use crate::{
|
|||||||
sys::UnsafeCommandBufferBuilder,
|
sys::UnsafeCommandBufferBuilder,
|
||||||
AutoCommandBufferBuilder, CopyError, CopyErrorResource,
|
AutoCommandBufferBuilder, CopyError, CopyErrorResource,
|
||||||
},
|
},
|
||||||
device::DeviceOwned,
|
device::{DeviceOwned, QueueFlags},
|
||||||
format::{ClearColorValue, ClearDepthStencilValue, NumericType},
|
format::{ClearColorValue, ClearDepthStencilValue, FormatFeatures, NumericType},
|
||||||
image::{
|
image::{
|
||||||
ImageAccess, ImageAspects, ImageDimensions, ImageLayout, ImageSubresourceLayers,
|
ImageAccess, ImageAspects, ImageDimensions, ImageLayout, ImageSubresourceLayers,
|
||||||
ImageSubresourceRange, ImageType, SampleCount, SampleCounts,
|
ImageSubresourceRange, ImageType, ImageUsage, SampleCount, SampleCounts,
|
||||||
},
|
},
|
||||||
sampler::Filter,
|
sampler::Filter,
|
||||||
sync::{AccessFlags, PipelineMemoryAccess, PipelineStages},
|
sync::{AccessFlags, PipelineMemoryAccess, PipelineStages},
|
||||||
@ -89,7 +89,10 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdBlitImage2-commandBuffer-cmdpool
|
// VUID-vkCmdBlitImage2-commandBuffer-cmdpool
|
||||||
if !queue_family_properties.queue_flags.graphics {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS)
|
||||||
|
{
|
||||||
return Err(CopyError::NotSupportedByQueueFamily);
|
return Err(CopyError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,7 +128,7 @@ where
|
|||||||
let dst_image_type = dst_image.dimensions().image_type();
|
let dst_image_type = dst_image.dimensions().image_type();
|
||||||
|
|
||||||
// VUID-VkBlitImageInfo2-srcImage-00219
|
// VUID-VkBlitImageInfo2-srcImage-00219
|
||||||
if !src_image.usage().transfer_src {
|
if !src_image.usage().intersects(ImageUsage::TRANSFER_SRC) {
|
||||||
return Err(CopyError::MissingUsage {
|
return Err(CopyError::MissingUsage {
|
||||||
resource: CopyErrorResource::Source,
|
resource: CopyErrorResource::Source,
|
||||||
usage: "transfer_src",
|
usage: "transfer_src",
|
||||||
@ -133,7 +136,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VUID-VkBlitImageInfo2-dstImage-00224
|
// VUID-VkBlitImageInfo2-dstImage-00224
|
||||||
if !dst_image.usage().transfer_dst {
|
if !dst_image.usage().intersects(ImageUsage::TRANSFER_DST) {
|
||||||
return Err(CopyError::MissingUsage {
|
return Err(CopyError::MissingUsage {
|
||||||
resource: CopyErrorResource::Destination,
|
resource: CopyErrorResource::Destination,
|
||||||
usage: "transfer_dst",
|
usage: "transfer_dst",
|
||||||
@ -141,7 +144,10 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VUID-VkBlitImageInfo2-srcImage-01999
|
// VUID-VkBlitImageInfo2-srcImage-01999
|
||||||
if !src_image.format_features().blit_src {
|
if !src_image
|
||||||
|
.format_features()
|
||||||
|
.intersects(FormatFeatures::BLIT_SRC)
|
||||||
|
{
|
||||||
return Err(CopyError::MissingFormatFeature {
|
return Err(CopyError::MissingFormatFeature {
|
||||||
resource: CopyErrorResource::Source,
|
resource: CopyErrorResource::Source,
|
||||||
format_feature: "blit_src",
|
format_feature: "blit_src",
|
||||||
@ -149,7 +155,10 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VUID-VkBlitImageInfo2-dstImage-02000
|
// VUID-VkBlitImageInfo2-dstImage-02000
|
||||||
if !dst_image.format_features().blit_dst {
|
if !dst_image
|
||||||
|
.format_features()
|
||||||
|
.intersects(FormatFeatures::BLIT_DST)
|
||||||
|
{
|
||||||
return Err(CopyError::MissingFormatFeature {
|
return Err(CopyError::MissingFormatFeature {
|
||||||
resource: CopyErrorResource::Destination,
|
resource: CopyErrorResource::Destination,
|
||||||
format_feature: "blit_dst",
|
format_feature: "blit_dst",
|
||||||
@ -172,7 +181,9 @@ where
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if !(src_image_aspects.color && dst_image_aspects.color) {
|
if !(src_image_aspects.intersects(ImageAspects::COLOR)
|
||||||
|
&& dst_image_aspects.intersects(ImageAspects::COLOR))
|
||||||
|
{
|
||||||
// VUID-VkBlitImageInfo2-srcImage-00231
|
// VUID-VkBlitImageInfo2-srcImage-00231
|
||||||
if src_image.format() != dst_image.format() {
|
if src_image.format() != dst_image.format() {
|
||||||
return Err(CopyError::FormatsMismatch {
|
return Err(CopyError::FormatsMismatch {
|
||||||
@ -218,10 +229,7 @@ where
|
|||||||
return Err(CopyError::SampleCountInvalid {
|
return Err(CopyError::SampleCountInvalid {
|
||||||
resource: CopyErrorResource::Destination,
|
resource: CopyErrorResource::Destination,
|
||||||
sample_count: dst_image.samples(),
|
sample_count: dst_image.samples(),
|
||||||
allowed_sample_counts: SampleCounts {
|
allowed_sample_counts: SampleCounts::SAMPLE_1,
|
||||||
sample1: true,
|
|
||||||
..SampleCounts::empty()
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,10 +238,7 @@ where
|
|||||||
return Err(CopyError::SampleCountInvalid {
|
return Err(CopyError::SampleCountInvalid {
|
||||||
resource: CopyErrorResource::Destination,
|
resource: CopyErrorResource::Destination,
|
||||||
sample_count: dst_image.samples(),
|
sample_count: dst_image.samples(),
|
||||||
allowed_sample_counts: SampleCounts {
|
allowed_sample_counts: SampleCounts::SAMPLE_1,
|
||||||
sample1: true,
|
|
||||||
..SampleCounts::empty()
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -260,7 +265,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VUID-VkBlitImageInfo2-srcImage-00232
|
// VUID-VkBlitImageInfo2-srcImage-00232
|
||||||
if !src_image_aspects.color && filter != Filter::Nearest {
|
if !src_image_aspects.intersects(ImageAspects::COLOR) && filter != Filter::Nearest {
|
||||||
return Err(CopyError::FilterNotSupportedByFormat);
|
return Err(CopyError::FilterNotSupportedByFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -268,13 +273,19 @@ where
|
|||||||
Filter::Nearest => (),
|
Filter::Nearest => (),
|
||||||
Filter::Linear => {
|
Filter::Linear => {
|
||||||
// VUID-VkBlitImageInfo2-filter-02001
|
// VUID-VkBlitImageInfo2-filter-02001
|
||||||
if !src_image.format_features().sampled_image_filter_linear {
|
if !src_image
|
||||||
|
.format_features()
|
||||||
|
.intersects(FormatFeatures::SAMPLED_IMAGE_FILTER_LINEAR)
|
||||||
|
{
|
||||||
return Err(CopyError::FilterNotSupportedByFormat);
|
return Err(CopyError::FilterNotSupportedByFormat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Filter::Cubic => {
|
Filter::Cubic => {
|
||||||
// VUID-VkBlitImageInfo2-filter-02002
|
// VUID-VkBlitImageInfo2-filter-02002
|
||||||
if !src_image.format_features().sampled_image_filter_cubic {
|
if !src_image
|
||||||
|
.format_features()
|
||||||
|
.intersects(FormatFeatures::SAMPLED_IMAGE_FILTER_CUBIC)
|
||||||
|
{
|
||||||
return Err(CopyError::FilterNotSupportedByFormat);
|
return Err(CopyError::FilterNotSupportedByFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -300,7 +311,7 @@ where
|
|||||||
|
|
||||||
let check_subresource = |resource: CopyErrorResource,
|
let check_subresource = |resource: CopyErrorResource,
|
||||||
image: &dyn ImageAccess,
|
image: &dyn ImageAccess,
|
||||||
image_aspects: &ImageAspects,
|
image_aspects: ImageAspects,
|
||||||
subresource: &ImageSubresourceLayers|
|
subresource: &ImageSubresourceLayers|
|
||||||
-> Result<_, CopyError> {
|
-> Result<_, CopyError> {
|
||||||
// VUID-VkBlitImageInfo2-srcSubresource-01705
|
// VUID-VkBlitImageInfo2-srcSubresource-01705
|
||||||
@ -337,12 +348,12 @@ where
|
|||||||
|
|
||||||
// VUID-VkBlitImageInfo2-aspectMask-00241
|
// VUID-VkBlitImageInfo2-aspectMask-00241
|
||||||
// VUID-VkBlitImageInfo2-aspectMask-00242
|
// VUID-VkBlitImageInfo2-aspectMask-00242
|
||||||
if !image_aspects.contains(&subresource.aspects) {
|
if !image_aspects.contains(subresource.aspects) {
|
||||||
return Err(CopyError::AspectsNotAllowed {
|
return Err(CopyError::AspectsNotAllowed {
|
||||||
resource,
|
resource,
|
||||||
region_index,
|
region_index,
|
||||||
aspects: subresource.aspects,
|
aspects: subresource.aspects,
|
||||||
allowed_aspects: *image_aspects,
|
allowed_aspects: image_aspects,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -356,13 +367,13 @@ where
|
|||||||
let src_subresource_extent = check_subresource(
|
let src_subresource_extent = check_subresource(
|
||||||
CopyErrorResource::Source,
|
CopyErrorResource::Source,
|
||||||
src_image,
|
src_image,
|
||||||
&src_image_aspects,
|
src_image_aspects,
|
||||||
src_subresource,
|
src_subresource,
|
||||||
)?;
|
)?;
|
||||||
let dst_subresource_extent = check_subresource(
|
let dst_subresource_extent = check_subresource(
|
||||||
CopyErrorResource::Destination,
|
CopyErrorResource::Destination,
|
||||||
dst_image,
|
dst_image,
|
||||||
&dst_image_aspects,
|
dst_image_aspects,
|
||||||
dst_subresource,
|
dst_subresource,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
@ -591,8 +602,9 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdClearColorImage-commandBuffer-cmdpool
|
// VUID-vkCmdClearColorImage-commandBuffer-cmdpool
|
||||||
if !(queue_family_properties.queue_flags.graphics
|
if !queue_family_properties
|
||||||
|| queue_family_properties.queue_flags.compute)
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS | QueueFlags::COMPUTE)
|
||||||
{
|
{
|
||||||
return Err(CopyError::NotSupportedByQueueFamily);
|
return Err(CopyError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
@ -612,7 +624,7 @@ where
|
|||||||
assert_eq!(device, image.device());
|
assert_eq!(device, image.device());
|
||||||
|
|
||||||
// VUID-vkCmdClearColorImage-image-00002
|
// VUID-vkCmdClearColorImage-image-00002
|
||||||
if !image.usage().transfer_dst {
|
if !image.usage().intersects(ImageUsage::TRANSFER_DST) {
|
||||||
return Err(CopyError::MissingUsage {
|
return Err(CopyError::MissingUsage {
|
||||||
resource: CopyErrorResource::Destination,
|
resource: CopyErrorResource::Destination,
|
||||||
usage: "transfer_dst",
|
usage: "transfer_dst",
|
||||||
@ -621,7 +633,10 @@ where
|
|||||||
|
|
||||||
if device.api_version() >= Version::V1_1 || device.enabled_extensions().khr_maintenance1 {
|
if device.api_version() >= Version::V1_1 || device.enabled_extensions().khr_maintenance1 {
|
||||||
// VUID-vkCmdClearColorImage-image-01993
|
// VUID-vkCmdClearColorImage-image-01993
|
||||||
if !image.format_features().transfer_dst {
|
if !image
|
||||||
|
.format_features()
|
||||||
|
.intersects(FormatFeatures::TRANSFER_DST)
|
||||||
|
{
|
||||||
return Err(CopyError::MissingFormatFeature {
|
return Err(CopyError::MissingFormatFeature {
|
||||||
resource: CopyErrorResource::Destination,
|
resource: CopyErrorResource::Destination,
|
||||||
format_feature: "transfer_dst",
|
format_feature: "transfer_dst",
|
||||||
@ -632,7 +647,7 @@ where
|
|||||||
let image_aspects = image.format().aspects();
|
let image_aspects = image.format().aspects();
|
||||||
|
|
||||||
// VUID-vkCmdClearColorImage-image-00007
|
// VUID-vkCmdClearColorImage-image-00007
|
||||||
if image_aspects.depth || image_aspects.stencil {
|
if image_aspects.intersects(ImageAspects::DEPTH | ImageAspects::STENCIL) {
|
||||||
return Err(CopyError::FormatNotSupported {
|
return Err(CopyError::FormatNotSupported {
|
||||||
resource: CopyErrorResource::Destination,
|
resource: CopyErrorResource::Destination,
|
||||||
format: image.format(),
|
format: image.format(),
|
||||||
@ -674,7 +689,7 @@ where
|
|||||||
assert!(!subresource_range.aspects.is_empty());
|
assert!(!subresource_range.aspects.is_empty());
|
||||||
|
|
||||||
// VUID-vkCmdClearColorImage-aspectMask-02498
|
// VUID-vkCmdClearColorImage-aspectMask-02498
|
||||||
if !image_aspects.contains(&subresource_range.aspects) {
|
if !image_aspects.contains(subresource_range.aspects) {
|
||||||
return Err(CopyError::AspectsNotAllowed {
|
return Err(CopyError::AspectsNotAllowed {
|
||||||
resource: CopyErrorResource::Destination,
|
resource: CopyErrorResource::Destination,
|
||||||
region_index,
|
region_index,
|
||||||
@ -743,7 +758,10 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdClearDepthStencilImage-commandBuffer-cmdpool
|
// VUID-vkCmdClearDepthStencilImage-commandBuffer-cmdpool
|
||||||
if !queue_family_properties.queue_flags.graphics {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS)
|
||||||
|
{
|
||||||
return Err(CopyError::NotSupportedByQueueFamily);
|
return Err(CopyError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -763,7 +781,10 @@ where
|
|||||||
|
|
||||||
if device.api_version() >= Version::V1_1 || device.enabled_extensions().khr_maintenance1 {
|
if device.api_version() >= Version::V1_1 || device.enabled_extensions().khr_maintenance1 {
|
||||||
// VUID-vkCmdClearDepthStencilImage-image-01994
|
// VUID-vkCmdClearDepthStencilImage-image-01994
|
||||||
if !image.format_features().transfer_dst {
|
if !image
|
||||||
|
.format_features()
|
||||||
|
.intersects(FormatFeatures::TRANSFER_DST)
|
||||||
|
{
|
||||||
return Err(CopyError::MissingFormatFeature {
|
return Err(CopyError::MissingFormatFeature {
|
||||||
resource: CopyErrorResource::Destination,
|
resource: CopyErrorResource::Destination,
|
||||||
format_feature: "transfer_dst",
|
format_feature: "transfer_dst",
|
||||||
@ -774,7 +795,7 @@ where
|
|||||||
let image_aspects = image.format().aspects();
|
let image_aspects = image.format().aspects();
|
||||||
|
|
||||||
// VUID-vkCmdClearDepthStencilImage-image-00014
|
// VUID-vkCmdClearDepthStencilImage-image-00014
|
||||||
if !(image_aspects.depth || image_aspects.stencil) {
|
if !image_aspects.intersects(ImageAspects::DEPTH | ImageAspects::STENCIL) {
|
||||||
return Err(CopyError::FormatNotSupported {
|
return Err(CopyError::FormatNotSupported {
|
||||||
resource: CopyErrorResource::Destination,
|
resource: CopyErrorResource::Destination,
|
||||||
format: image.format(),
|
format: image.format(),
|
||||||
@ -797,8 +818,8 @@ where
|
|||||||
&& !(0.0..=1.0).contains(&clear_value.depth)
|
&& !(0.0..=1.0).contains(&clear_value.depth)
|
||||||
{
|
{
|
||||||
return Err(CopyError::RequirementNotMet {
|
return Err(CopyError::RequirementNotMet {
|
||||||
required_for:
|
required_for: "`clear_info.clear_value.depth` is not between `0.0` and `1.0` \
|
||||||
"`clear_info.clear_value.depth` is not between `0.0` and `1.0` inclusive",
|
inclusive",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
device_extensions: &["ext_depth_range_unrestricted"],
|
device_extensions: &["ext_depth_range_unrestricted"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -818,7 +839,7 @@ where
|
|||||||
// VUID-vkCmdClearDepthStencilImage-aspectMask-02824
|
// VUID-vkCmdClearDepthStencilImage-aspectMask-02824
|
||||||
// VUID-vkCmdClearDepthStencilImage-image-02825
|
// VUID-vkCmdClearDepthStencilImage-image-02825
|
||||||
// VUID-vkCmdClearDepthStencilImage-image-02826
|
// VUID-vkCmdClearDepthStencilImage-image-02826
|
||||||
if !image_aspects.contains(&subresource_range.aspects) {
|
if !image_aspects.contains(subresource_range.aspects) {
|
||||||
return Err(CopyError::AspectsNotAllowed {
|
return Err(CopyError::AspectsNotAllowed {
|
||||||
resource: CopyErrorResource::Destination,
|
resource: CopyErrorResource::Destination,
|
||||||
region_index,
|
region_index,
|
||||||
@ -860,7 +881,9 @@ where
|
|||||||
|
|
||||||
// VUID-vkCmdClearDepthStencilImage-pRanges-02658
|
// VUID-vkCmdClearDepthStencilImage-pRanges-02658
|
||||||
// VUID-vkCmdClearDepthStencilImage-pRanges-02659
|
// VUID-vkCmdClearDepthStencilImage-pRanges-02659
|
||||||
if image_aspects_used.stencil && !image.stencil_usage().transfer_dst {
|
if image_aspects_used.intersects(ImageAspects::STENCIL)
|
||||||
|
&& !image.stencil_usage().intersects(ImageUsage::TRANSFER_DST)
|
||||||
|
{
|
||||||
return Err(CopyError::MissingUsage {
|
return Err(CopyError::MissingUsage {
|
||||||
resource: CopyErrorResource::Destination,
|
resource: CopyErrorResource::Destination,
|
||||||
usage: "transfer_dst",
|
usage: "transfer_dst",
|
||||||
@ -868,12 +891,8 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VUID-vkCmdClearDepthStencilImage-pRanges-02660
|
// VUID-vkCmdClearDepthStencilImage-pRanges-02660
|
||||||
if !(ImageAspects {
|
if !(image_aspects_used - ImageAspects::STENCIL).is_empty()
|
||||||
stencil: false,
|
&& !image.usage().intersects(ImageUsage::TRANSFER_DST)
|
||||||
..image_aspects_used
|
|
||||||
})
|
|
||||||
.is_empty()
|
|
||||||
&& !image.usage().transfer_dst
|
|
||||||
{
|
{
|
||||||
return Err(CopyError::MissingUsage {
|
return Err(CopyError::MissingUsage {
|
||||||
resource: CopyErrorResource::Destination,
|
resource: CopyErrorResource::Destination,
|
||||||
@ -917,7 +936,10 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdResolveImage2-commandBuffer-cmdpool
|
// VUID-vkCmdResolveImage2-commandBuffer-cmdpool
|
||||||
if !queue_family_properties.queue_flags.graphics {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS)
|
||||||
|
{
|
||||||
return Err(CopyError::NotSupportedByQueueFamily);
|
return Err(CopyError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -948,15 +970,12 @@ where
|
|||||||
return Err(CopyError::SampleCountInvalid {
|
return Err(CopyError::SampleCountInvalid {
|
||||||
resource: CopyErrorResource::Source,
|
resource: CopyErrorResource::Source,
|
||||||
sample_count: dst_image.samples(),
|
sample_count: dst_image.samples(),
|
||||||
allowed_sample_counts: SampleCounts {
|
allowed_sample_counts: SampleCounts::SAMPLE_2
|
||||||
sample2: true,
|
| SampleCounts::SAMPLE_4
|
||||||
sample4: true,
|
| SampleCounts::SAMPLE_8
|
||||||
sample8: true,
|
| SampleCounts::SAMPLE_16
|
||||||
sample16: true,
|
| SampleCounts::SAMPLE_32
|
||||||
sample32: true,
|
| SampleCounts::SAMPLE_64,
|
||||||
sample64: true,
|
|
||||||
..SampleCounts::empty()
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -965,15 +984,15 @@ where
|
|||||||
return Err(CopyError::SampleCountInvalid {
|
return Err(CopyError::SampleCountInvalid {
|
||||||
resource: CopyErrorResource::Destination,
|
resource: CopyErrorResource::Destination,
|
||||||
sample_count: dst_image.samples(),
|
sample_count: dst_image.samples(),
|
||||||
allowed_sample_counts: SampleCounts {
|
allowed_sample_counts: SampleCounts::SAMPLE_1,
|
||||||
sample1: true,
|
|
||||||
..SampleCounts::empty()
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// VUID-VkResolveImageInfo2-dstImage-02003
|
// VUID-VkResolveImageInfo2-dstImage-02003
|
||||||
if !dst_image.format_features().color_attachment {
|
if !dst_image
|
||||||
|
.format_features()
|
||||||
|
.intersects(FormatFeatures::COLOR_ATTACHMENT)
|
||||||
|
{
|
||||||
return Err(CopyError::MissingFormatFeature {
|
return Err(CopyError::MissingFormatFeature {
|
||||||
resource: CopyErrorResource::Destination,
|
resource: CopyErrorResource::Destination,
|
||||||
format_feature: "color_attachment",
|
format_feature: "color_attachment",
|
||||||
@ -1012,7 +1031,10 @@ where
|
|||||||
|
|
||||||
// Should be guaranteed by the requirement that formats match, and that the destination
|
// Should be guaranteed by the requirement that formats match, and that the destination
|
||||||
// image format features support color attachments.
|
// image format features support color attachments.
|
||||||
debug_assert!(src_image.format().aspects().color && dst_image.format().aspects().color);
|
debug_assert!(
|
||||||
|
src_image.format().aspects().intersects(ImageAspects::COLOR)
|
||||||
|
&& dst_image.format().aspects().intersects(ImageAspects::COLOR)
|
||||||
|
);
|
||||||
|
|
||||||
for (region_index, region) in regions.iter().enumerate() {
|
for (region_index, region) in regions.iter().enumerate() {
|
||||||
let &ImageResolve {
|
let &ImageResolve {
|
||||||
@ -1062,20 +1084,12 @@ where
|
|||||||
|
|
||||||
// VUID-VkImageSubresourceLayers-aspectMask-requiredbitmask
|
// VUID-VkImageSubresourceLayers-aspectMask-requiredbitmask
|
||||||
// VUID-VkImageResolve2-aspectMask-00266
|
// VUID-VkImageResolve2-aspectMask-00266
|
||||||
if subresource.aspects
|
if subresource.aspects != (ImageAspects::COLOR) {
|
||||||
!= (ImageAspects {
|
|
||||||
color: true,
|
|
||||||
..ImageAspects::empty()
|
|
||||||
})
|
|
||||||
{
|
|
||||||
return Err(CopyError::AspectsNotAllowed {
|
return Err(CopyError::AspectsNotAllowed {
|
||||||
resource,
|
resource,
|
||||||
region_index,
|
region_index,
|
||||||
aspects: subresource.aspects,
|
aspects: subresource.aspects,
|
||||||
allowed_aspects: ImageAspects {
|
allowed_aspects: ImageAspects::COLOR,
|
||||||
color: true,
|
|
||||||
..ImageAspects::empty()
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1216,14 +1230,8 @@ impl SyncCommandBufferBuilder {
|
|||||||
image: src_image.clone(),
|
image: src_image.clone(),
|
||||||
subresource_range: src_subresource.clone().into(),
|
subresource_range: src_subresource.clone().into(),
|
||||||
memory: PipelineMemoryAccess {
|
memory: PipelineMemoryAccess {
|
||||||
stages: PipelineStages {
|
stages: PipelineStages::ALL_TRANSFER,
|
||||||
all_transfer: true,
|
access: AccessFlags::TRANSFER_READ,
|
||||||
..PipelineStages::empty()
|
|
||||||
},
|
|
||||||
access: AccessFlags {
|
|
||||||
transfer_read: true,
|
|
||||||
..AccessFlags::empty()
|
|
||||||
},
|
|
||||||
exclusive: false,
|
exclusive: false,
|
||||||
},
|
},
|
||||||
start_layout: src_image_layout,
|
start_layout: src_image_layout,
|
||||||
@ -1236,14 +1244,8 @@ impl SyncCommandBufferBuilder {
|
|||||||
image: dst_image.clone(),
|
image: dst_image.clone(),
|
||||||
subresource_range: dst_subresource.clone().into(),
|
subresource_range: dst_subresource.clone().into(),
|
||||||
memory: PipelineMemoryAccess {
|
memory: PipelineMemoryAccess {
|
||||||
stages: PipelineStages {
|
stages: PipelineStages::ALL_TRANSFER,
|
||||||
all_transfer: true,
|
access: AccessFlags::TRANSFER_WRITE,
|
||||||
..PipelineStages::empty()
|
|
||||||
},
|
|
||||||
access: AccessFlags {
|
|
||||||
transfer_write: true,
|
|
||||||
..AccessFlags::empty()
|
|
||||||
},
|
|
||||||
exclusive: true,
|
exclusive: true,
|
||||||
},
|
},
|
||||||
start_layout: dst_image_layout,
|
start_layout: dst_image_layout,
|
||||||
@ -1308,14 +1310,8 @@ impl SyncCommandBufferBuilder {
|
|||||||
image: image.clone(),
|
image: image.clone(),
|
||||||
subresource_range,
|
subresource_range,
|
||||||
memory: PipelineMemoryAccess {
|
memory: PipelineMemoryAccess {
|
||||||
stages: PipelineStages {
|
stages: PipelineStages::ALL_TRANSFER,
|
||||||
all_transfer: true,
|
access: AccessFlags::TRANSFER_WRITE,
|
||||||
..PipelineStages::empty()
|
|
||||||
},
|
|
||||||
access: AccessFlags {
|
|
||||||
transfer_write: true,
|
|
||||||
..AccessFlags::empty()
|
|
||||||
},
|
|
||||||
exclusive: true,
|
exclusive: true,
|
||||||
},
|
},
|
||||||
start_layout: image_layout,
|
start_layout: image_layout,
|
||||||
@ -1379,14 +1375,8 @@ impl SyncCommandBufferBuilder {
|
|||||||
image: image.clone(),
|
image: image.clone(),
|
||||||
subresource_range,
|
subresource_range,
|
||||||
memory: PipelineMemoryAccess {
|
memory: PipelineMemoryAccess {
|
||||||
stages: PipelineStages {
|
stages: PipelineStages::ALL_TRANSFER,
|
||||||
all_transfer: true,
|
access: AccessFlags::TRANSFER_WRITE,
|
||||||
..PipelineStages::empty()
|
|
||||||
},
|
|
||||||
access: AccessFlags {
|
|
||||||
transfer_write: true,
|
|
||||||
..AccessFlags::empty()
|
|
||||||
},
|
|
||||||
exclusive: true,
|
exclusive: true,
|
||||||
},
|
},
|
||||||
start_layout: image_layout,
|
start_layout: image_layout,
|
||||||
@ -1460,14 +1450,8 @@ impl SyncCommandBufferBuilder {
|
|||||||
image: src_image.clone(),
|
image: src_image.clone(),
|
||||||
subresource_range: src_subresource.clone().into(),
|
subresource_range: src_subresource.clone().into(),
|
||||||
memory: PipelineMemoryAccess {
|
memory: PipelineMemoryAccess {
|
||||||
stages: PipelineStages {
|
stages: PipelineStages::ALL_TRANSFER,
|
||||||
all_transfer: true,
|
access: AccessFlags::TRANSFER_READ,
|
||||||
..PipelineStages::empty()
|
|
||||||
},
|
|
||||||
access: AccessFlags {
|
|
||||||
transfer_read: true,
|
|
||||||
..AccessFlags::empty()
|
|
||||||
},
|
|
||||||
exclusive: false,
|
exclusive: false,
|
||||||
},
|
},
|
||||||
start_layout: src_image_layout,
|
start_layout: src_image_layout,
|
||||||
@ -1480,14 +1464,8 @@ impl SyncCommandBufferBuilder {
|
|||||||
image: dst_image.clone(),
|
image: dst_image.clone(),
|
||||||
subresource_range: dst_subresource.clone().into(),
|
subresource_range: dst_subresource.clone().into(),
|
||||||
memory: PipelineMemoryAccess {
|
memory: PipelineMemoryAccess {
|
||||||
stages: PipelineStages {
|
stages: PipelineStages::ALL_TRANSFER,
|
||||||
all_transfer: true,
|
access: AccessFlags::TRANSFER_WRITE,
|
||||||
..PipelineStages::empty()
|
|
||||||
},
|
|
||||||
access: AccessFlags {
|
|
||||||
transfer_write: true,
|
|
||||||
..AccessFlags::empty()
|
|
||||||
},
|
|
||||||
exclusive: true,
|
exclusive: true,
|
||||||
},
|
},
|
||||||
start_layout: dst_image_layout,
|
start_layout: dst_image_layout,
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
// according to those terms.
|
// according to those terms.
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
buffer::{view::BufferViewAbstract, BufferAccess, TypedBufferAccess},
|
buffer::{view::BufferViewAbstract, BufferAccess, BufferUsage, TypedBufferAccess},
|
||||||
command_buffer::{
|
command_buffer::{
|
||||||
allocator::CommandBufferAllocator,
|
allocator::CommandBufferAllocator,
|
||||||
auto::{RenderPassState, RenderPassStateType},
|
auto::{RenderPassState, RenderPassStateType},
|
||||||
@ -18,10 +18,11 @@ use crate::{
|
|||||||
DrawIndirectCommand, SubpassContents,
|
DrawIndirectCommand, SubpassContents,
|
||||||
},
|
},
|
||||||
descriptor_set::{layout::DescriptorType, DescriptorBindingResources},
|
descriptor_set::{layout::DescriptorType, DescriptorBindingResources},
|
||||||
device::DeviceOwned,
|
device::{DeviceOwned, QueueFlags},
|
||||||
format::Format,
|
format::{Format, FormatFeatures},
|
||||||
image::{
|
image::{
|
||||||
view::ImageViewType, ImageAccess, ImageSubresourceRange, ImageViewAbstract, SampleCount,
|
view::ImageViewType, ImageAccess, ImageAspects, ImageSubresourceRange, ImageViewAbstract,
|
||||||
|
SampleCount,
|
||||||
},
|
},
|
||||||
pipeline::{
|
pipeline::{
|
||||||
graphics::{
|
graphics::{
|
||||||
@ -76,7 +77,10 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdDispatch-commandBuffer-cmdpool
|
// VUID-vkCmdDispatch-commandBuffer-cmdpool
|
||||||
if !queue_family_properties.queue_flags.compute {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::COMPUTE)
|
||||||
|
{
|
||||||
return Err(PipelineExecutionError::NotSupportedByQueueFamily);
|
return Err(PipelineExecutionError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,7 +146,10 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdDispatchIndirect-commandBuffer-cmdpool
|
// VUID-vkCmdDispatchIndirect-commandBuffer-cmdpool
|
||||||
if !queue_family_properties.queue_flags.compute {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::COMPUTE)
|
||||||
|
{
|
||||||
return Err(PipelineExecutionError::NotSupportedByQueueFamily);
|
return Err(PipelineExecutionError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -549,7 +556,7 @@ where
|
|||||||
assert_eq!(self.device(), buffer.device());
|
assert_eq!(self.device(), buffer.device());
|
||||||
|
|
||||||
// VUID-vkCmdDispatchIndirect-buffer-02709
|
// VUID-vkCmdDispatchIndirect-buffer-02709
|
||||||
if !buffer.inner().buffer.usage().indirect_buffer {
|
if !buffer.usage().intersects(BufferUsage::INDIRECT_BUFFER) {
|
||||||
return Err(PipelineExecutionError::IndirectBufferMissingUsage);
|
return Err(PipelineExecutionError::IndirectBufferMissingUsage);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -650,7 +657,9 @@ where
|
|||||||
// VUID-vkCmdDispatch-OpTypeImage-06423
|
// VUID-vkCmdDispatch-OpTypeImage-06423
|
||||||
if reqs.image_format.is_none()
|
if reqs.image_format.is_none()
|
||||||
&& reqs.storage_write.contains(&index)
|
&& reqs.storage_write.contains(&index)
|
||||||
&& !buffer_view.format_features().storage_write_without_format
|
&& !buffer_view
|
||||||
|
.format_features()
|
||||||
|
.intersects(FormatFeatures::STORAGE_WRITE_WITHOUT_FORMAT)
|
||||||
{
|
{
|
||||||
return Err(
|
return Err(
|
||||||
DescriptorResourceInvalidError::StorageWriteWithoutFormatNotSupported,
|
DescriptorResourceInvalidError::StorageWriteWithoutFormatNotSupported,
|
||||||
@ -660,7 +669,9 @@ where
|
|||||||
// VUID-vkCmdDispatch-OpTypeImage-06424
|
// VUID-vkCmdDispatch-OpTypeImage-06424
|
||||||
if reqs.image_format.is_none()
|
if reqs.image_format.is_none()
|
||||||
&& reqs.storage_read.contains(&index)
|
&& reqs.storage_read.contains(&index)
|
||||||
&& !buffer_view.format_features().storage_read_without_format
|
&& !buffer_view
|
||||||
|
.format_features()
|
||||||
|
.intersects(FormatFeatures::STORAGE_READ_WITHOUT_FORMAT)
|
||||||
{
|
{
|
||||||
return Err(
|
return Err(
|
||||||
DescriptorResourceInvalidError::StorageReadWithoutFormatNotSupported,
|
DescriptorResourceInvalidError::StorageReadWithoutFormatNotSupported,
|
||||||
@ -674,7 +685,9 @@ where
|
|||||||
let check_image_view_common = |index: u32, image_view: &Arc<dyn ImageViewAbstract>| {
|
let check_image_view_common = |index: u32, image_view: &Arc<dyn ImageViewAbstract>| {
|
||||||
// VUID-vkCmdDispatch-None-02691
|
// VUID-vkCmdDispatch-None-02691
|
||||||
if reqs.storage_image_atomic.contains(&index)
|
if reqs.storage_image_atomic.contains(&index)
|
||||||
&& !image_view.format_features().storage_image_atomic
|
&& !image_view
|
||||||
|
.format_features()
|
||||||
|
.intersects(FormatFeatures::STORAGE_IMAGE_ATOMIC)
|
||||||
{
|
{
|
||||||
return Err(DescriptorResourceInvalidError::StorageImageAtomicNotSupported);
|
return Err(DescriptorResourceInvalidError::StorageImageAtomicNotSupported);
|
||||||
}
|
}
|
||||||
@ -683,7 +696,9 @@ where
|
|||||||
// VUID-vkCmdDispatch-OpTypeImage-06423
|
// VUID-vkCmdDispatch-OpTypeImage-06423
|
||||||
if reqs.image_format.is_none()
|
if reqs.image_format.is_none()
|
||||||
&& reqs.storage_write.contains(&index)
|
&& reqs.storage_write.contains(&index)
|
||||||
&& !image_view.format_features().storage_write_without_format
|
&& !image_view
|
||||||
|
.format_features()
|
||||||
|
.intersects(FormatFeatures::STORAGE_WRITE_WITHOUT_FORMAT)
|
||||||
{
|
{
|
||||||
return Err(
|
return Err(
|
||||||
DescriptorResourceInvalidError::StorageWriteWithoutFormatNotSupported,
|
DescriptorResourceInvalidError::StorageWriteWithoutFormatNotSupported,
|
||||||
@ -693,7 +708,9 @@ where
|
|||||||
// VUID-vkCmdDispatch-OpTypeImage-06424
|
// VUID-vkCmdDispatch-OpTypeImage-06424
|
||||||
if reqs.image_format.is_none()
|
if reqs.image_format.is_none()
|
||||||
&& reqs.storage_read.contains(&index)
|
&& reqs.storage_read.contains(&index)
|
||||||
&& !image_view.format_features().storage_read_without_format
|
&& !image_view
|
||||||
|
.format_features()
|
||||||
|
.intersects(FormatFeatures::STORAGE_READ_WITHOUT_FORMAT)
|
||||||
{
|
{
|
||||||
return Err(
|
return Err(
|
||||||
DescriptorResourceInvalidError::StorageReadWithoutFormatNotSupported,
|
DescriptorResourceInvalidError::StorageReadWithoutFormatNotSupported,
|
||||||
@ -748,11 +765,16 @@ where
|
|||||||
if let Some(scalar_type) = reqs.image_scalar_type {
|
if let Some(scalar_type) = reqs.image_scalar_type {
|
||||||
let aspects = image_view.subresource_range().aspects;
|
let aspects = image_view.subresource_range().aspects;
|
||||||
let view_scalar_type = ShaderScalarType::from(
|
let view_scalar_type = ShaderScalarType::from(
|
||||||
if aspects.color || aspects.plane0 || aspects.plane1 || aspects.plane2 {
|
if aspects.intersects(
|
||||||
|
ImageAspects::COLOR
|
||||||
|
| ImageAspects::PLANE_0
|
||||||
|
| ImageAspects::PLANE_1
|
||||||
|
| ImageAspects::PLANE_2,
|
||||||
|
) {
|
||||||
image_view.format().unwrap().type_color().unwrap()
|
image_view.format().unwrap().type_color().unwrap()
|
||||||
} else if aspects.depth {
|
} else if aspects.intersects(ImageAspects::DEPTH) {
|
||||||
image_view.format().unwrap().type_depth().unwrap()
|
image_view.format().unwrap().type_depth().unwrap()
|
||||||
} else if aspects.stencil {
|
} else if aspects.intersects(ImageAspects::STENCIL) {
|
||||||
image_view.format().unwrap().type_stencil().unwrap()
|
image_view.format().unwrap().type_stencil().unwrap()
|
||||||
} else {
|
} else {
|
||||||
// Per `ImageViewBuilder::aspects` and
|
// Per `ImageViewBuilder::aspects` and
|
||||||
@ -1125,7 +1147,10 @@ where
|
|||||||
// VUID?
|
// VUID?
|
||||||
if !device.enabled_features().primitive_topology_list_restart {
|
if !device.enabled_features().primitive_topology_list_restart {
|
||||||
return Err(PipelineExecutionError::RequirementNotMet {
|
return Err(PipelineExecutionError::RequirementNotMet {
|
||||||
required_for: "The bound pipeline sets `DynamicState::PrimitiveRestartEnable` and the current primitive topology is `PrimitiveTopology::*List`",
|
required_for: "The bound pipeline sets \
|
||||||
|
`DynamicState::PrimitiveRestartEnable` and the \
|
||||||
|
current primitive topology is \
|
||||||
|
`PrimitiveTopology::*List`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["primitive_topology_list_restart"],
|
features: &["primitive_topology_list_restart"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -1140,7 +1165,10 @@ where
|
|||||||
.primitive_topology_patch_list_restart
|
.primitive_topology_patch_list_restart
|
||||||
{
|
{
|
||||||
return Err(PipelineExecutionError::RequirementNotMet {
|
return Err(PipelineExecutionError::RequirementNotMet {
|
||||||
required_for: "The bound pipeline sets `DynamicState::PrimitiveRestartEnable` and the current primitive topology is `PrimitiveTopology::PatchList`",
|
required_for: "The bound pipeline sets \
|
||||||
|
`DynamicState::PrimitiveRestartEnable` and the \
|
||||||
|
current primitive topology is \
|
||||||
|
`PrimitiveTopology::PatchList`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["primitive_topology_patch_list_restart"],
|
features: &["primitive_topology_patch_list_restart"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -1934,20 +1962,10 @@ impl SyncCommandBufferBuilder {
|
|||||||
| DescriptorType::UniformTexelBuffer
|
| DescriptorType::UniformTexelBuffer
|
||||||
| DescriptorType::StorageTexelBuffer
|
| DescriptorType::StorageTexelBuffer
|
||||||
| DescriptorType::StorageBuffer
|
| DescriptorType::StorageBuffer
|
||||||
| DescriptorType::StorageBufferDynamic => AccessFlags {
|
| DescriptorType::StorageBufferDynamic => AccessFlags::SHADER_READ,
|
||||||
shader_read: true,
|
DescriptorType::InputAttachment => AccessFlags::INPUT_ATTACHMENT_READ,
|
||||||
shader_write: false,
|
|
||||||
..AccessFlags::empty()
|
|
||||||
},
|
|
||||||
DescriptorType::InputAttachment => AccessFlags {
|
|
||||||
input_attachment_read: true,
|
|
||||||
..AccessFlags::empty()
|
|
||||||
},
|
|
||||||
DescriptorType::UniformBuffer | DescriptorType::UniformBufferDynamic => {
|
DescriptorType::UniformBuffer | DescriptorType::UniformBufferDynamic => {
|
||||||
AccessFlags {
|
AccessFlags::UNIFORM_READ
|
||||||
uniform_read: true,
|
|
||||||
..AccessFlags::empty()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
exclusive: false,
|
exclusive: false,
|
||||||
@ -1956,8 +1974,12 @@ impl SyncCommandBufferBuilder {
|
|||||||
let access = (0..).map(|index| {
|
let access = (0..).map(|index| {
|
||||||
let mut access = access;
|
let mut access = access;
|
||||||
let mutable = reqs.storage_write.contains(&index);
|
let mutable = reqs.storage_write.contains(&index);
|
||||||
access.access.shader_write = mutable;
|
|
||||||
access.exclusive = mutable;
|
access.exclusive = mutable;
|
||||||
|
|
||||||
|
if mutable {
|
||||||
|
access.access |= AccessFlags::SHADER_WRITE;
|
||||||
|
}
|
||||||
|
|
||||||
access
|
access
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -2080,14 +2102,8 @@ impl SyncCommandBufferBuilder {
|
|||||||
buffer: vertex_buffer.clone(),
|
buffer: vertex_buffer.clone(),
|
||||||
range: 0..vertex_buffer.size(), // TODO:
|
range: 0..vertex_buffer.size(), // TODO:
|
||||||
memory: PipelineMemoryAccess {
|
memory: PipelineMemoryAccess {
|
||||||
stages: PipelineStages {
|
stages: PipelineStages::VERTEX_INPUT,
|
||||||
vertex_input: true,
|
access: AccessFlags::VERTEX_ATTRIBUTE_READ,
|
||||||
..PipelineStages::empty()
|
|
||||||
},
|
|
||||||
access: AccessFlags {
|
|
||||||
vertex_attribute_read: true,
|
|
||||||
..AccessFlags::empty()
|
|
||||||
},
|
|
||||||
exclusive: false,
|
exclusive: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -2103,14 +2119,8 @@ impl SyncCommandBufferBuilder {
|
|||||||
buffer: index_buffer.clone(),
|
buffer: index_buffer.clone(),
|
||||||
range: 0..index_buffer.size(), // TODO:
|
range: 0..index_buffer.size(), // TODO:
|
||||||
memory: PipelineMemoryAccess {
|
memory: PipelineMemoryAccess {
|
||||||
stages: PipelineStages {
|
stages: PipelineStages::VERTEX_INPUT,
|
||||||
vertex_input: true,
|
access: AccessFlags::INDEX_READ,
|
||||||
..PipelineStages::empty()
|
|
||||||
},
|
|
||||||
access: AccessFlags {
|
|
||||||
index_read: true,
|
|
||||||
..AccessFlags::empty()
|
|
||||||
},
|
|
||||||
exclusive: false,
|
exclusive: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -2128,14 +2138,8 @@ impl SyncCommandBufferBuilder {
|
|||||||
buffer: indirect_buffer.clone(),
|
buffer: indirect_buffer.clone(),
|
||||||
range: 0..indirect_buffer.size(), // TODO:
|
range: 0..indirect_buffer.size(), // TODO:
|
||||||
memory: PipelineMemoryAccess {
|
memory: PipelineMemoryAccess {
|
||||||
stages: PipelineStages {
|
stages: PipelineStages::DRAW_INDIRECT, // TODO: is draw_indirect correct for dispatch too?
|
||||||
draw_indirect: true,
|
access: AccessFlags::INDIRECT_COMMAND_READ,
|
||||||
..PipelineStages::empty()
|
|
||||||
}, // TODO: is draw_indirect correct for dispatch too?
|
|
||||||
access: AccessFlags {
|
|
||||||
indirect_command_read: true,
|
|
||||||
..AccessFlags::empty()
|
|
||||||
},
|
|
||||||
exclusive: false,
|
exclusive: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -2174,7 +2178,10 @@ impl UnsafeCommandBufferBuilder {
|
|||||||
|
|
||||||
let inner = buffer.inner();
|
let inner = buffer.inner();
|
||||||
debug_assert!(inner.offset < inner.buffer.size());
|
debug_assert!(inner.offset < inner.buffer.size());
|
||||||
debug_assert!(inner.buffer.usage().indirect_buffer);
|
debug_assert!(inner
|
||||||
|
.buffer
|
||||||
|
.usage()
|
||||||
|
.intersects(BufferUsage::INDIRECT_BUFFER));
|
||||||
debug_assert_eq!(inner.offset % 4, 0);
|
debug_assert_eq!(inner.offset % 4, 0);
|
||||||
|
|
||||||
(fns.v1_0.cmd_dispatch_indirect)(self.handle, inner.buffer.handle(), inner.offset);
|
(fns.v1_0.cmd_dispatch_indirect)(self.handle, inner.buffer.handle(), inner.offset);
|
||||||
@ -2238,7 +2245,10 @@ impl UnsafeCommandBufferBuilder {
|
|||||||
|
|
||||||
let inner = buffer.inner();
|
let inner = buffer.inner();
|
||||||
debug_assert!(inner.offset < inner.buffer.size());
|
debug_assert!(inner.offset < inner.buffer.size());
|
||||||
debug_assert!(inner.buffer.usage().indirect_buffer);
|
debug_assert!(inner
|
||||||
|
.buffer
|
||||||
|
.usage()
|
||||||
|
.intersects(BufferUsage::INDIRECT_BUFFER));
|
||||||
|
|
||||||
(fns.v1_0.cmd_draw_indirect)(
|
(fns.v1_0.cmd_draw_indirect)(
|
||||||
self.handle,
|
self.handle,
|
||||||
@ -2261,7 +2271,10 @@ impl UnsafeCommandBufferBuilder {
|
|||||||
|
|
||||||
let inner = buffer.inner();
|
let inner = buffer.inner();
|
||||||
debug_assert!(inner.offset < inner.buffer.size());
|
debug_assert!(inner.offset < inner.buffer.size());
|
||||||
debug_assert!(inner.buffer.usage().indirect_buffer);
|
debug_assert!(inner
|
||||||
|
.buffer
|
||||||
|
.usage()
|
||||||
|
.intersects(BufferUsage::INDIRECT_BUFFER));
|
||||||
|
|
||||||
(fns.v1_0.cmd_draw_indexed_indirect)(
|
(fns.v1_0.cmd_draw_indexed_indirect)(
|
||||||
self.handle,
|
self.handle,
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
// according to those terms.
|
// according to those terms.
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
buffer::TypedBufferAccess,
|
buffer::{BufferUsage, TypedBufferAccess},
|
||||||
command_buffer::{
|
command_buffer::{
|
||||||
allocator::CommandBufferAllocator,
|
allocator::CommandBufferAllocator,
|
||||||
auto::QueryState,
|
auto::QueryState,
|
||||||
@ -16,7 +16,7 @@ use crate::{
|
|||||||
sys::UnsafeCommandBufferBuilder,
|
sys::UnsafeCommandBufferBuilder,
|
||||||
AutoCommandBufferBuilder,
|
AutoCommandBufferBuilder,
|
||||||
},
|
},
|
||||||
device::DeviceOwned,
|
device::{DeviceOwned, QueueFlags},
|
||||||
query::{
|
query::{
|
||||||
QueriesRange, Query, QueryControlFlags, QueryPool, QueryResultElement, QueryResultFlags,
|
QueriesRange, Query, QueryControlFlags, QueryPool, QueryResultElement, QueryResultFlags,
|
||||||
QueryType,
|
QueryType,
|
||||||
@ -80,8 +80,9 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdBeginQuery-commandBuffer-cmdpool
|
// VUID-vkCmdBeginQuery-commandBuffer-cmdpool
|
||||||
if !(queue_family_properties.queue_flags.graphics
|
if !queue_family_properties
|
||||||
|| queue_family_properties.queue_flags.compute)
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS | QueueFlags::COMPUTE)
|
||||||
{
|
{
|
||||||
return Err(QueryError::NotSupportedByQueueFamily);
|
return Err(QueryError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
@ -101,14 +102,19 @@ where
|
|||||||
QueryType::Occlusion => {
|
QueryType::Occlusion => {
|
||||||
// VUID-vkCmdBeginQuery-commandBuffer-cmdpool
|
// VUID-vkCmdBeginQuery-commandBuffer-cmdpool
|
||||||
// // VUID-vkCmdBeginQuery-queryType-00803
|
// // VUID-vkCmdBeginQuery-queryType-00803
|
||||||
if !queue_family_properties.queue_flags.graphics {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS)
|
||||||
|
{
|
||||||
return Err(QueryError::NotSupportedByQueueFamily);
|
return Err(QueryError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
// VUID-vkCmdBeginQuery-queryType-00800
|
// VUID-vkCmdBeginQuery-queryType-00800
|
||||||
if flags.precise && !device.enabled_features().occlusion_query_precise {
|
if flags.intersects(QueryControlFlags::PRECISE)
|
||||||
|
&& !device.enabled_features().occlusion_query_precise
|
||||||
|
{
|
||||||
return Err(QueryError::RequirementNotMet {
|
return Err(QueryError::RequirementNotMet {
|
||||||
required_for: "`flags.precise` is set",
|
required_for: "`flags` contains `QueryControlFlags::PRECISE`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["occlusion_query_precise"],
|
features: &["occlusion_query_precise"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -120,15 +126,20 @@ where
|
|||||||
// VUID-vkCmdBeginQuery-commandBuffer-cmdpool
|
// VUID-vkCmdBeginQuery-commandBuffer-cmdpool
|
||||||
// VUID-vkCmdBeginQuery-queryType-00804
|
// VUID-vkCmdBeginQuery-queryType-00804
|
||||||
// VUID-vkCmdBeginQuery-queryType-00805
|
// VUID-vkCmdBeginQuery-queryType-00805
|
||||||
if statistic_flags.is_compute() && !queue_family_properties.queue_flags.compute
|
if statistic_flags.is_compute()
|
||||||
|
&& !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::COMPUTE)
|
||||||
|| statistic_flags.is_graphics()
|
|| statistic_flags.is_graphics()
|
||||||
&& !queue_family_properties.queue_flags.graphics
|
&& !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS)
|
||||||
{
|
{
|
||||||
return Err(QueryError::NotSupportedByQueueFamily);
|
return Err(QueryError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
// VUID-vkCmdBeginQuery-queryType-00800
|
// VUID-vkCmdBeginQuery-queryType-00800
|
||||||
if flags.precise {
|
if flags.intersects(QueryControlFlags::PRECISE) {
|
||||||
return Err(QueryError::InvalidFlags);
|
return Err(QueryError::InvalidFlags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -179,8 +190,9 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdEndQuery-commandBuffer-cmdpool
|
// VUID-vkCmdEndQuery-commandBuffer-cmdpool
|
||||||
if !(queue_family_properties.queue_flags.graphics
|
if !queue_family_properties
|
||||||
|| queue_family_properties.queue_flags.compute)
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS | QueueFlags::COMPUTE)
|
||||||
{
|
{
|
||||||
return Err(QueryError::NotSupportedByQueueFamily);
|
return Err(QueryError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
@ -243,7 +255,7 @@ where
|
|||||||
|
|
||||||
if !device.enabled_features().synchronization2 && PipelineStages::from(stage).is_2() {
|
if !device.enabled_features().synchronization2 && PipelineStages::from(stage).is_2() {
|
||||||
return Err(QueryError::RequirementNotMet {
|
return Err(QueryError::RequirementNotMet {
|
||||||
required_for: "`stage` has bits set from `VkPipelineStageFlagBits2`",
|
required_for: "`stage` has flags set from `VkPipelineStageFlagBits2`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["synchronization2"],
|
features: &["synchronization2"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -257,12 +269,13 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdWriteTimestamp2-commandBuffer-cmdpool
|
// VUID-vkCmdWriteTimestamp2-commandBuffer-cmdpool
|
||||||
if !(queue_family_properties.queue_flags.transfer
|
if !queue_family_properties.queue_flags.intersects(
|
||||||
|| queue_family_properties.queue_flags.graphics
|
QueueFlags::TRANSFER
|
||||||
|| queue_family_properties.queue_flags.compute
|
| QueueFlags::GRAPHICS
|
||||||
|| queue_family_properties.queue_flags.video_decode
|
| QueueFlags::COMPUTE
|
||||||
|| queue_family_properties.queue_flags.video_encode)
|
| QueueFlags::VIDEO_DECODE
|
||||||
{
|
| QueueFlags::VIDEO_ENCODE,
|
||||||
|
) {
|
||||||
return Err(QueryError::NotSupportedByQueueFamily);
|
return Err(QueryError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,7 +307,8 @@ where
|
|||||||
// VUID-vkCmdWriteTimestamp2-stage-03930
|
// VUID-vkCmdWriteTimestamp2-stage-03930
|
||||||
if !device.enabled_features().tessellation_shader {
|
if !device.enabled_features().tessellation_shader {
|
||||||
return Err(QueryError::RequirementNotMet {
|
return Err(QueryError::RequirementNotMet {
|
||||||
required_for: "`stage` is `PipelineStage::TessellationControlShader` or `PipelineStage::TessellationEvaluationShader`",
|
required_for: "`stage` is `PipelineStage::TessellationControlShader` or \
|
||||||
|
`PipelineStage::TessellationEvaluationShader`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["tessellation_shader"],
|
features: &["tessellation_shader"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -433,12 +447,15 @@ where
|
|||||||
|
|
||||||
/// Copies the results of a range of queries to a buffer on the GPU.
|
/// Copies the results of a range of queries to a buffer on the GPU.
|
||||||
///
|
///
|
||||||
/// [`query_pool.ty().result_len()`](crate::query::QueryType::result_len) elements
|
/// [`query_pool.ty().result_len()`] elements will be written for each query in the range, plus
|
||||||
/// will be written for each query in the range, plus 1 extra element per query if
|
/// 1 extra element per query if [`QueryResultFlags::WITH_AVAILABILITY`] is enabled.
|
||||||
/// [`QueryResultFlags::with_availability`] is enabled.
|
|
||||||
/// The provided buffer must be large enough to hold the data.
|
/// The provided buffer must be large enough to hold the data.
|
||||||
///
|
///
|
||||||
/// See also [`get_results`](crate::query::QueriesRange::get_results).
|
/// See also [`get_results`].
|
||||||
|
///
|
||||||
|
/// [`query_pool.ty().result_len()`]: crate::query::QueryType::result_len
|
||||||
|
/// [`QueryResultFlags::WITH_AVAILABILITY`]: crate::query::QueryResultFlags::WITH_AVAILABILITY
|
||||||
|
/// [`get_results`]: crate::query::QueriesRange::get_results
|
||||||
pub fn copy_query_pool_results<D, T>(
|
pub fn copy_query_pool_results<D, T>(
|
||||||
&mut self,
|
&mut self,
|
||||||
query_pool: Arc<QueryPool>,
|
query_pool: Arc<QueryPool>,
|
||||||
@ -458,8 +475,8 @@ where
|
|||||||
)?;
|
)?;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let per_query_len =
|
let per_query_len = query_pool.query_type().result_len()
|
||||||
query_pool.query_type().result_len() + flags.with_availability as DeviceSize;
|
+ flags.intersects(QueryResultFlags::WITH_AVAILABILITY) as DeviceSize;
|
||||||
let stride = per_query_len * std::mem::size_of::<T>() as DeviceSize;
|
let stride = per_query_len * std::mem::size_of::<T>() as DeviceSize;
|
||||||
self.inner
|
self.inner
|
||||||
.copy_query_pool_results(query_pool, queries, destination, stride, flags)?;
|
.copy_query_pool_results(query_pool, queries, destination, stride, flags)?;
|
||||||
@ -482,8 +499,9 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdCopyQueryPoolResults-commandBuffer-cmdpool
|
// VUID-vkCmdCopyQueryPoolResults-commandBuffer-cmdpool
|
||||||
if !(queue_family_properties.queue_flags.graphics
|
if !queue_family_properties
|
||||||
|| queue_family_properties.queue_flags.compute)
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS | QueueFlags::COMPUTE)
|
||||||
{
|
{
|
||||||
return Err(QueryError::NotSupportedByQueueFamily);
|
return Err(QueryError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
@ -513,8 +531,8 @@ where
|
|||||||
.ok_or(QueryError::OutOfRange)?;
|
.ok_or(QueryError::OutOfRange)?;
|
||||||
|
|
||||||
let count = queries.end - queries.start;
|
let count = queries.end - queries.start;
|
||||||
let per_query_len =
|
let per_query_len = query_pool.query_type().result_len()
|
||||||
query_pool.query_type().result_len() + flags.with_availability as DeviceSize;
|
+ flags.intersects(QueryResultFlags::WITH_AVAILABILITY) as DeviceSize;
|
||||||
let required_len = per_query_len * count as DeviceSize;
|
let required_len = per_query_len * count as DeviceSize;
|
||||||
|
|
||||||
// VUID-vkCmdCopyQueryPoolResults-dstBuffer-00824
|
// VUID-vkCmdCopyQueryPoolResults-dstBuffer-00824
|
||||||
@ -526,12 +544,18 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VUID-vkCmdCopyQueryPoolResults-dstBuffer-00825
|
// VUID-vkCmdCopyQueryPoolResults-dstBuffer-00825
|
||||||
if !buffer_inner.buffer.usage().transfer_dst {
|
if !buffer_inner
|
||||||
|
.buffer
|
||||||
|
.usage()
|
||||||
|
.intersects(BufferUsage::TRANSFER_DST)
|
||||||
|
{
|
||||||
return Err(QueryError::DestinationMissingUsage);
|
return Err(QueryError::DestinationMissingUsage);
|
||||||
}
|
}
|
||||||
|
|
||||||
// VUID-vkCmdCopyQueryPoolResults-queryType-00827
|
// VUID-vkCmdCopyQueryPoolResults-queryType-00827
|
||||||
if matches!(query_pool.query_type(), QueryType::Timestamp) && flags.partial {
|
if matches!(query_pool.query_type(), QueryType::Timestamp)
|
||||||
|
&& flags.intersects(QueryResultFlags::PARTIAL)
|
||||||
|
{
|
||||||
return Err(QueryError::InvalidFlags);
|
return Err(QueryError::InvalidFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -571,8 +595,9 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdResetQueryPool-commandBuffer-cmdpool
|
// VUID-vkCmdResetQueryPool-commandBuffer-cmdpool
|
||||||
if !(queue_family_properties.queue_flags.graphics
|
if !queue_family_properties
|
||||||
|| queue_family_properties.queue_flags.compute)
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS | QueueFlags::COMPUTE)
|
||||||
{
|
{
|
||||||
return Err(QueryError::NotSupportedByQueueFamily);
|
return Err(QueryError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
@ -734,14 +759,8 @@ impl SyncCommandBufferBuilder {
|
|||||||
buffer: destination.clone(),
|
buffer: destination.clone(),
|
||||||
range: 0..destination.size(), // TODO:
|
range: 0..destination.size(), // TODO:
|
||||||
memory: PipelineMemoryAccess {
|
memory: PipelineMemoryAccess {
|
||||||
stages: PipelineStages {
|
stages: PipelineStages::ALL_TRANSFER,
|
||||||
all_transfer: true,
|
access: AccessFlags::TRANSFER_WRITE,
|
||||||
..PipelineStages::empty()
|
|
||||||
},
|
|
||||||
access: AccessFlags {
|
|
||||||
transfer_write: true,
|
|
||||||
..AccessFlags::empty()
|
|
||||||
},
|
|
||||||
exclusive: true,
|
exclusive: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -796,12 +815,12 @@ impl UnsafeCommandBufferBuilder {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn begin_query(&mut self, query: Query<'_>, flags: QueryControlFlags) {
|
pub unsafe fn begin_query(&mut self, query: Query<'_>, flags: QueryControlFlags) {
|
||||||
let fns = self.device.fns();
|
let fns = self.device.fns();
|
||||||
let flags = if flags.precise {
|
(fns.v1_0.cmd_begin_query)(
|
||||||
ash::vk::QueryControlFlags::PRECISE
|
self.handle,
|
||||||
} else {
|
query.pool().handle(),
|
||||||
ash::vk::QueryControlFlags::empty()
|
query.index(),
|
||||||
};
|
flags.into(),
|
||||||
(fns.v1_0.cmd_begin_query)(self.handle, query.pool().handle(), query.index(), flags);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calls `vkCmdEndQuery` on the builder.
|
/// Calls `vkCmdEndQuery` on the builder.
|
||||||
@ -857,7 +876,10 @@ impl UnsafeCommandBufferBuilder {
|
|||||||
let destination = destination.inner();
|
let destination = destination.inner();
|
||||||
let range = queries.range();
|
let range = queries.range();
|
||||||
debug_assert!(destination.offset < destination.buffer.size());
|
debug_assert!(destination.offset < destination.buffer.size());
|
||||||
debug_assert!(destination.buffer.usage().transfer_dst);
|
debug_assert!(destination
|
||||||
|
.buffer
|
||||||
|
.usage()
|
||||||
|
.intersects(BufferUsage::TRANSFER_DST));
|
||||||
debug_assert!(destination.offset % size_of::<T>() as DeviceSize == 0);
|
debug_assert!(destination.offset % size_of::<T>() as DeviceSize == 0);
|
||||||
debug_assert!(stride % size_of::<T>() as DeviceSize == 0);
|
debug_assert!(stride % size_of::<T>() as DeviceSize == 0);
|
||||||
|
|
||||||
|
@ -18,9 +18,9 @@ use crate::{
|
|||||||
sys::UnsafeCommandBufferBuilder,
|
sys::UnsafeCommandBufferBuilder,
|
||||||
AutoCommandBufferBuilder, SubpassContents,
|
AutoCommandBufferBuilder, SubpassContents,
|
||||||
},
|
},
|
||||||
device::DeviceOwned,
|
device::{DeviceOwned, QueueFlags},
|
||||||
format::{ClearColorValue, ClearValue, Format, NumericType},
|
format::{ClearColorValue, ClearValue, Format, NumericType},
|
||||||
image::{ImageLayout, ImageViewAbstract, SampleCount},
|
image::{ImageAspects, ImageLayout, ImageUsage, ImageViewAbstract, SampleCount},
|
||||||
render_pass::{
|
render_pass::{
|
||||||
AttachmentDescription, Framebuffer, LoadOp, RenderPass, ResolveMode, StoreOp,
|
AttachmentDescription, Framebuffer, LoadOp, RenderPass, ResolveMode, StoreOp,
|
||||||
SubpassDescription,
|
SubpassDescription,
|
||||||
@ -103,7 +103,10 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdBeginRenderPass2-commandBuffer-cmdpool
|
// VUID-vkCmdBeginRenderPass2-commandBuffer-cmdpool
|
||||||
if !queue_family_properties.queue_flags.graphics {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS)
|
||||||
|
{
|
||||||
return Err(RenderPassError::NotSupportedByQueueFamily);
|
return Err(RenderPassError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,7 +158,7 @@ where
|
|||||||
match layout {
|
match layout {
|
||||||
ImageLayout::ColorAttachmentOptimal => {
|
ImageLayout::ColorAttachmentOptimal => {
|
||||||
// VUID-vkCmdBeginRenderPass2-initialLayout-03094
|
// VUID-vkCmdBeginRenderPass2-initialLayout-03094
|
||||||
if !image_view.usage().color_attachment {
|
if !image_view.usage().intersects(ImageUsage::COLOR_ATTACHMENT) {
|
||||||
return Err(RenderPassError::AttachmentImageMissingUsage {
|
return Err(RenderPassError::AttachmentImageMissingUsage {
|
||||||
attachment_index,
|
attachment_index,
|
||||||
usage: "color_attachment",
|
usage: "color_attachment",
|
||||||
@ -167,7 +170,10 @@ where
|
|||||||
| ImageLayout::DepthStencilAttachmentOptimal
|
| ImageLayout::DepthStencilAttachmentOptimal
|
||||||
| ImageLayout::DepthStencilReadOnlyOptimal => {
|
| ImageLayout::DepthStencilReadOnlyOptimal => {
|
||||||
// VUID-vkCmdBeginRenderPass2-initialLayout-03096
|
// VUID-vkCmdBeginRenderPass2-initialLayout-03096
|
||||||
if !image_view.usage().depth_stencil_attachment {
|
if !image_view
|
||||||
|
.usage()
|
||||||
|
.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
|
||||||
|
{
|
||||||
return Err(RenderPassError::AttachmentImageMissingUsage {
|
return Err(RenderPassError::AttachmentImageMissingUsage {
|
||||||
attachment_index,
|
attachment_index,
|
||||||
usage: "depth_stencil_attachment",
|
usage: "depth_stencil_attachment",
|
||||||
@ -176,7 +182,10 @@ where
|
|||||||
}
|
}
|
||||||
ImageLayout::ShaderReadOnlyOptimal => {
|
ImageLayout::ShaderReadOnlyOptimal => {
|
||||||
// VUID-vkCmdBeginRenderPass2-initialLayout-03097
|
// VUID-vkCmdBeginRenderPass2-initialLayout-03097
|
||||||
if !(image_view.usage().sampled || image_view.usage().input_attachment) {
|
if !image_view
|
||||||
|
.usage()
|
||||||
|
.intersects(ImageUsage::SAMPLED | ImageUsage::INPUT_ATTACHMENT)
|
||||||
|
{
|
||||||
return Err(RenderPassError::AttachmentImageMissingUsage {
|
return Err(RenderPassError::AttachmentImageMissingUsage {
|
||||||
attachment_index,
|
attachment_index,
|
||||||
usage: "sampled or input_attachment",
|
usage: "sampled or input_attachment",
|
||||||
@ -185,7 +194,7 @@ where
|
|||||||
}
|
}
|
||||||
ImageLayout::TransferSrcOptimal => {
|
ImageLayout::TransferSrcOptimal => {
|
||||||
// VUID-vkCmdBeginRenderPass2-initialLayout-03098
|
// VUID-vkCmdBeginRenderPass2-initialLayout-03098
|
||||||
if !image_view.usage().transfer_src {
|
if !image_view.usage().intersects(ImageUsage::TRANSFER_SRC) {
|
||||||
return Err(RenderPassError::AttachmentImageMissingUsage {
|
return Err(RenderPassError::AttachmentImageMissingUsage {
|
||||||
attachment_index,
|
attachment_index,
|
||||||
usage: "transfer_src",
|
usage: "transfer_src",
|
||||||
@ -194,7 +203,7 @@ where
|
|||||||
}
|
}
|
||||||
ImageLayout::TransferDstOptimal => {
|
ImageLayout::TransferDstOptimal => {
|
||||||
// VUID-vkCmdBeginRenderPass2-initialLayout-03099
|
// VUID-vkCmdBeginRenderPass2-initialLayout-03099
|
||||||
if !image_view.usage().transfer_dst {
|
if !image_view.usage().intersects(ImageUsage::TRANSFER_DST) {
|
||||||
return Err(RenderPassError::AttachmentImageMissingUsage {
|
return Err(RenderPassError::AttachmentImageMissingUsage {
|
||||||
attachment_index,
|
attachment_index,
|
||||||
usage: "transfer_dst",
|
usage: "transfer_dst",
|
||||||
@ -228,7 +237,7 @@ where
|
|||||||
match atch_ref.layout {
|
match atch_ref.layout {
|
||||||
ImageLayout::ColorAttachmentOptimal => {
|
ImageLayout::ColorAttachmentOptimal => {
|
||||||
// VUID-vkCmdBeginRenderPass2-initialLayout-03094
|
// VUID-vkCmdBeginRenderPass2-initialLayout-03094
|
||||||
if !image_view.usage().color_attachment {
|
if !image_view.usage().intersects(ImageUsage::COLOR_ATTACHMENT) {
|
||||||
return Err(RenderPassError::AttachmentImageMissingUsage {
|
return Err(RenderPassError::AttachmentImageMissingUsage {
|
||||||
attachment_index: atch_ref.attachment,
|
attachment_index: atch_ref.attachment,
|
||||||
usage: "color_attachment",
|
usage: "color_attachment",
|
||||||
@ -240,7 +249,10 @@ where
|
|||||||
| ImageLayout::DepthStencilAttachmentOptimal
|
| ImageLayout::DepthStencilAttachmentOptimal
|
||||||
| ImageLayout::DepthStencilReadOnlyOptimal => {
|
| ImageLayout::DepthStencilReadOnlyOptimal => {
|
||||||
// VUID-vkCmdBeginRenderPass2-initialLayout-03096
|
// VUID-vkCmdBeginRenderPass2-initialLayout-03096
|
||||||
if !image_view.usage().depth_stencil_attachment {
|
if !image_view
|
||||||
|
.usage()
|
||||||
|
.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
|
||||||
|
{
|
||||||
return Err(RenderPassError::AttachmentImageMissingUsage {
|
return Err(RenderPassError::AttachmentImageMissingUsage {
|
||||||
attachment_index: atch_ref.attachment,
|
attachment_index: atch_ref.attachment,
|
||||||
usage: "depth_stencil_attachment",
|
usage: "depth_stencil_attachment",
|
||||||
@ -249,7 +261,10 @@ where
|
|||||||
}
|
}
|
||||||
ImageLayout::ShaderReadOnlyOptimal => {
|
ImageLayout::ShaderReadOnlyOptimal => {
|
||||||
// VUID-vkCmdBeginRenderPass2-initialLayout-03097
|
// VUID-vkCmdBeginRenderPass2-initialLayout-03097
|
||||||
if !(image_view.usage().sampled || image_view.usage().input_attachment) {
|
if !image_view
|
||||||
|
.usage()
|
||||||
|
.intersects(ImageUsage::SAMPLED | ImageUsage::INPUT_ATTACHMENT)
|
||||||
|
{
|
||||||
return Err(RenderPassError::AttachmentImageMissingUsage {
|
return Err(RenderPassError::AttachmentImageMissingUsage {
|
||||||
attachment_index: atch_ref.attachment,
|
attachment_index: atch_ref.attachment,
|
||||||
usage: "sampled or input_attachment",
|
usage: "sampled or input_attachment",
|
||||||
@ -258,7 +273,7 @@ where
|
|||||||
}
|
}
|
||||||
ImageLayout::TransferSrcOptimal => {
|
ImageLayout::TransferSrcOptimal => {
|
||||||
// VUID-vkCmdBeginRenderPass2-initialLayout-03098
|
// VUID-vkCmdBeginRenderPass2-initialLayout-03098
|
||||||
if !image_view.usage().transfer_src {
|
if !image_view.usage().intersects(ImageUsage::TRANSFER_SRC) {
|
||||||
return Err(RenderPassError::AttachmentImageMissingUsage {
|
return Err(RenderPassError::AttachmentImageMissingUsage {
|
||||||
attachment_index: atch_ref.attachment,
|
attachment_index: atch_ref.attachment,
|
||||||
usage: "transfer_src",
|
usage: "transfer_src",
|
||||||
@ -267,7 +282,7 @@ where
|
|||||||
}
|
}
|
||||||
ImageLayout::TransferDstOptimal => {
|
ImageLayout::TransferDstOptimal => {
|
||||||
// VUID-vkCmdBeginRenderPass2-initialLayout-03099
|
// VUID-vkCmdBeginRenderPass2-initialLayout-03099
|
||||||
if !image_view.usage().transfer_dst {
|
if !image_view.usage().intersects(ImageUsage::TRANSFER_DST) {
|
||||||
return Err(RenderPassError::AttachmentImageMissingUsage {
|
return Err(RenderPassError::AttachmentImageMissingUsage {
|
||||||
attachment_index: atch_ref.attachment,
|
attachment_index: atch_ref.attachment,
|
||||||
usage: "transfer_dst",
|
usage: "transfer_dst",
|
||||||
@ -344,9 +359,9 @@ where
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let attachment_aspects = attachment_format.aspects();
|
let attachment_aspects = attachment_format.aspects();
|
||||||
let need_depth =
|
let need_depth = attachment_aspects.intersects(ImageAspects::DEPTH)
|
||||||
attachment_aspects.depth && attachment_desc.load_op == LoadOp::Clear;
|
&& attachment_desc.load_op == LoadOp::Clear;
|
||||||
let need_stencil = attachment_aspects.stencil
|
let need_stencil = attachment_aspects.intersects(ImageAspects::STENCIL)
|
||||||
&& attachment_desc.stencil_load_op == LoadOp::Clear;
|
&& attachment_desc.stencil_load_op == LoadOp::Clear;
|
||||||
|
|
||||||
if need_depth && need_stencil {
|
if need_depth && need_stencil {
|
||||||
@ -456,10 +471,10 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VUID-vkCmdNextSubpass2-commandBuffer-cmdpool
|
// VUID-vkCmdNextSubpass2-commandBuffer-cmdpool
|
||||||
debug_assert!({
|
debug_assert!(self
|
||||||
let queue_family_properties = self.queue_family_properties();
|
.queue_family_properties()
|
||||||
queue_family_properties.queue_flags.graphics
|
.queue_flags
|
||||||
});
|
.intersects(QueueFlags::GRAPHICS));
|
||||||
|
|
||||||
// VUID-vkCmdNextSubpass2-bufferlevel
|
// VUID-vkCmdNextSubpass2-bufferlevel
|
||||||
// Ensured by the type of the impl block
|
// Ensured by the type of the impl block
|
||||||
@ -514,10 +529,10 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VUID-vkCmdEndRenderPass2-commandBuffer-cmdpool
|
// VUID-vkCmdEndRenderPass2-commandBuffer-cmdpool
|
||||||
debug_assert!({
|
debug_assert!(self
|
||||||
let queue_family_properties = self.queue_family_properties();
|
.queue_family_properties()
|
||||||
queue_family_properties.queue_flags.graphics
|
.queue_flags
|
||||||
});
|
.intersects(QueueFlags::GRAPHICS));
|
||||||
|
|
||||||
// VUID-vkCmdEndRenderPass2-bufferlevel
|
// VUID-vkCmdEndRenderPass2-bufferlevel
|
||||||
// Ensured by the type of the impl block
|
// Ensured by the type of the impl block
|
||||||
@ -678,7 +693,7 @@ where
|
|||||||
// VUID-vkCmdBeginRendering-dynamicRendering-06446
|
// VUID-vkCmdBeginRendering-dynamicRendering-06446
|
||||||
if !device.enabled_features().dynamic_rendering {
|
if !device.enabled_features().dynamic_rendering {
|
||||||
return Err(RenderPassError::RequirementNotMet {
|
return Err(RenderPassError::RequirementNotMet {
|
||||||
required_for: "`begin_rendering`",
|
required_for: "`AutoCommandBufferBuilder::begin_rendering`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["dynamic_rendering"],
|
features: &["dynamic_rendering"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -689,7 +704,10 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdBeginRendering-commandBuffer-cmdpool
|
// VUID-vkCmdBeginRendering-commandBuffer-cmdpool
|
||||||
if !queue_family_properties.queue_flags.graphics {
|
if !queue_family_properties
|
||||||
|
.queue_flags
|
||||||
|
.intersects(QueueFlags::GRAPHICS)
|
||||||
|
{
|
||||||
return Err(RenderPassError::NotSupportedByQueueFamily);
|
return Err(RenderPassError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -785,7 +803,7 @@ where
|
|||||||
store_op.validate_device(device)?;
|
store_op.validate_device(device)?;
|
||||||
|
|
||||||
// VUID-VkRenderingInfo-colorAttachmentCount-06087
|
// VUID-VkRenderingInfo-colorAttachmentCount-06087
|
||||||
if !image_view.usage().color_attachment {
|
if !image_view.usage().intersects(ImageUsage::COLOR_ATTACHMENT) {
|
||||||
return Err(RenderPassError::ColorAttachmentMissingUsage { attachment_index });
|
return Err(RenderPassError::ColorAttachmentMissingUsage { attachment_index });
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -942,12 +960,15 @@ where
|
|||||||
let image_aspects = image_view.format().unwrap().aspects();
|
let image_aspects = image_view.format().unwrap().aspects();
|
||||||
|
|
||||||
// VUID-VkRenderingInfo-pDepthAttachment-06547
|
// VUID-VkRenderingInfo-pDepthAttachment-06547
|
||||||
if !image_aspects.depth {
|
if !image_aspects.intersects(ImageAspects::DEPTH) {
|
||||||
return Err(RenderPassError::DepthAttachmentFormatUsageNotSupported);
|
return Err(RenderPassError::DepthAttachmentFormatUsageNotSupported);
|
||||||
}
|
}
|
||||||
|
|
||||||
// VUID-VkRenderingInfo-pDepthAttachment-06088
|
// VUID-VkRenderingInfo-pDepthAttachment-06088
|
||||||
if !image_view.usage().depth_stencil_attachment {
|
if !image_view
|
||||||
|
.usage()
|
||||||
|
.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
|
||||||
|
{
|
||||||
return Err(RenderPassError::DepthAttachmentMissingUsage);
|
return Err(RenderPassError::DepthAttachmentMissingUsage);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1003,7 +1024,7 @@ where
|
|||||||
// VUID-VkRenderingInfo-pDepthAttachment-06102
|
// VUID-VkRenderingInfo-pDepthAttachment-06102
|
||||||
if !properties
|
if !properties
|
||||||
.supported_depth_resolve_modes
|
.supported_depth_resolve_modes
|
||||||
.map_or(false, |modes| modes.contains_mode(mode))
|
.map_or(false, |modes| modes.contains_enum(mode))
|
||||||
{
|
{
|
||||||
return Err(RenderPassError::DepthAttachmentResolveModeNotSupported);
|
return Err(RenderPassError::DepthAttachmentResolveModeNotSupported);
|
||||||
}
|
}
|
||||||
@ -1069,12 +1090,15 @@ where
|
|||||||
let image_aspects = image_view.format().unwrap().aspects();
|
let image_aspects = image_view.format().unwrap().aspects();
|
||||||
|
|
||||||
// VUID-VkRenderingInfo-pStencilAttachment-06548
|
// VUID-VkRenderingInfo-pStencilAttachment-06548
|
||||||
if !image_aspects.stencil {
|
if !image_aspects.intersects(ImageAspects::STENCIL) {
|
||||||
return Err(RenderPassError::StencilAttachmentFormatUsageNotSupported);
|
return Err(RenderPassError::StencilAttachmentFormatUsageNotSupported);
|
||||||
}
|
}
|
||||||
|
|
||||||
// VUID-VkRenderingInfo-pStencilAttachment-06089
|
// VUID-VkRenderingInfo-pStencilAttachment-06089
|
||||||
if !image_view.usage().depth_stencil_attachment {
|
if !image_view
|
||||||
|
.usage()
|
||||||
|
.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
|
||||||
|
{
|
||||||
return Err(RenderPassError::StencilAttachmentMissingUsage);
|
return Err(RenderPassError::StencilAttachmentMissingUsage);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1130,7 +1154,7 @@ where
|
|||||||
// VUID-VkRenderingInfo-pStencilAttachment-06103
|
// VUID-VkRenderingInfo-pStencilAttachment-06103
|
||||||
if !properties
|
if !properties
|
||||||
.supported_stencil_resolve_modes
|
.supported_stencil_resolve_modes
|
||||||
.map_or(false, |modes| modes.contains_mode(mode))
|
.map_or(false, |modes| modes.contains_enum(mode))
|
||||||
{
|
{
|
||||||
return Err(RenderPassError::StencilAttachmentResolveModeNotSupported);
|
return Err(RenderPassError::StencilAttachmentResolveModeNotSupported);
|
||||||
}
|
}
|
||||||
@ -1251,10 +1275,10 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VUID-vkCmdEndRendering-commandBuffer-cmdpool
|
// VUID-vkCmdEndRendering-commandBuffer-cmdpool
|
||||||
debug_assert!({
|
debug_assert!(self
|
||||||
let queue_family_properties = self.queue_family_properties();
|
.queue_family_properties()
|
||||||
queue_family_properties.queue_flags.graphics
|
.queue_flags
|
||||||
});
|
.intersects(QueueFlags::GRAPHICS));
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -1416,8 +1440,9 @@ where
|
|||||||
if matches!(
|
if matches!(
|
||||||
clear_attachment,
|
clear_attachment,
|
||||||
ClearAttachment::Depth(_) | ClearAttachment::DepthStencil(_)
|
ClearAttachment::Depth(_) | ClearAttachment::DepthStencil(_)
|
||||||
) && !depth_format.map_or(false, |format| format.aspects().depth)
|
) && !depth_format.map_or(false, |format| {
|
||||||
{
|
format.aspects().intersects(ImageAspects::DEPTH)
|
||||||
|
}) {
|
||||||
return Err(RenderPassError::ClearAttachmentNotCompatible {
|
return Err(RenderPassError::ClearAttachmentNotCompatible {
|
||||||
clear_attachment,
|
clear_attachment,
|
||||||
attachment_format: None,
|
attachment_format: None,
|
||||||
@ -1428,8 +1453,9 @@ where
|
|||||||
if matches!(
|
if matches!(
|
||||||
clear_attachment,
|
clear_attachment,
|
||||||
ClearAttachment::Stencil(_) | ClearAttachment::DepthStencil(_)
|
ClearAttachment::Stencil(_) | ClearAttachment::DepthStencil(_)
|
||||||
) && !stencil_format.map_or(false, |format| format.aspects().stencil)
|
) && !stencil_format.map_or(false, |format| {
|
||||||
{
|
format.aspects().intersects(ImageAspects::STENCIL)
|
||||||
|
}) {
|
||||||
return Err(RenderPassError::ClearAttachmentNotCompatible {
|
return Err(RenderPassError::ClearAttachmentNotCompatible {
|
||||||
clear_attachment,
|
clear_attachment,
|
||||||
attachment_format: None,
|
attachment_format: None,
|
||||||
@ -1502,10 +1528,10 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VUID-vkCmdClearAttachments-commandBuffer-cmdpool
|
// VUID-vkCmdClearAttachments-commandBuffer-cmdpool
|
||||||
debug_assert!({
|
debug_assert!(self
|
||||||
let queue_family_properties = self.queue_family_properties();
|
.queue_family_properties()
|
||||||
queue_family_properties.queue_flags.graphics
|
.queue_flags
|
||||||
});
|
.intersects(QueueFlags::GRAPHICS));
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -1559,18 +1585,12 @@ impl SyncCommandBufferBuilder {
|
|||||||
image: image_view.image(),
|
image: image_view.image(),
|
||||||
subresource_range: image_view.subresource_range().clone(),
|
subresource_range: image_view.subresource_range().clone(),
|
||||||
memory: PipelineMemoryAccess {
|
memory: PipelineMemoryAccess {
|
||||||
stages: PipelineStages {
|
stages: PipelineStages::ALL_COMMANDS, // TODO: wrong!
|
||||||
all_commands: true,
|
access: AccessFlags::INPUT_ATTACHMENT_READ
|
||||||
..PipelineStages::empty()
|
| AccessFlags::COLOR_ATTACHMENT_READ
|
||||||
}, // TODO: wrong!
|
| AccessFlags::COLOR_ATTACHMENT_WRITE
|
||||||
access: AccessFlags {
|
| AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ
|
||||||
input_attachment_read: true,
|
| AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE, // TODO: suboptimal
|
||||||
color_attachment_read: true,
|
|
||||||
color_attachment_write: true,
|
|
||||||
depth_stencil_attachment_read: true,
|
|
||||||
depth_stencil_attachment_write: true,
|
|
||||||
..AccessFlags::empty()
|
|
||||||
}, // TODO: suboptimal
|
|
||||||
exclusive: true, // TODO: suboptimal ; note: remember to always pass true if desc.initial_layout != desc.final_layout
|
exclusive: true, // TODO: suboptimal ; note: remember to always pass true if desc.initial_layout != desc.final_layout
|
||||||
},
|
},
|
||||||
start_layout: desc.initial_layout,
|
start_layout: desc.initial_layout,
|
||||||
@ -1696,16 +1716,10 @@ impl SyncCommandBufferBuilder {
|
|||||||
image: image_view.image(),
|
image: image_view.image(),
|
||||||
subresource_range: image_view.subresource_range().clone(),
|
subresource_range: image_view.subresource_range().clone(),
|
||||||
memory: PipelineMemoryAccess {
|
memory: PipelineMemoryAccess {
|
||||||
stages: PipelineStages {
|
stages: PipelineStages::ALL_COMMANDS, // TODO: wrong!
|
||||||
all_commands: true,
|
access: AccessFlags::COLOR_ATTACHMENT_READ
|
||||||
..PipelineStages::empty()
|
| AccessFlags::COLOR_ATTACHMENT_WRITE, // TODO: suboptimal
|
||||||
}, // TODO: wrong!
|
exclusive: true, // TODO: suboptimal
|
||||||
access: AccessFlags {
|
|
||||||
color_attachment_read: true,
|
|
||||||
color_attachment_write: true,
|
|
||||||
..AccessFlags::empty()
|
|
||||||
}, // TODO: suboptimal
|
|
||||||
exclusive: true, // TODO: suboptimal
|
|
||||||
},
|
},
|
||||||
start_layout: image_layout,
|
start_layout: image_layout,
|
||||||
end_layout: image_layout,
|
end_layout: image_layout,
|
||||||
@ -1724,16 +1738,10 @@ impl SyncCommandBufferBuilder {
|
|||||||
image: image_view.image(),
|
image: image_view.image(),
|
||||||
subresource_range: image_view.subresource_range().clone(),
|
subresource_range: image_view.subresource_range().clone(),
|
||||||
memory: PipelineMemoryAccess {
|
memory: PipelineMemoryAccess {
|
||||||
stages: PipelineStages {
|
stages: PipelineStages::ALL_COMMANDS, // TODO: wrong!
|
||||||
all_commands: true,
|
access: AccessFlags::COLOR_ATTACHMENT_READ
|
||||||
..PipelineStages::empty()
|
| AccessFlags::COLOR_ATTACHMENT_WRITE, // TODO: suboptimal
|
||||||
}, // TODO: wrong!
|
exclusive: true, // TODO: suboptimal
|
||||||
access: AccessFlags {
|
|
||||||
color_attachment_read: true,
|
|
||||||
color_attachment_write: true,
|
|
||||||
..AccessFlags::empty()
|
|
||||||
}, // TODO: suboptimal
|
|
||||||
exclusive: true, // TODO: suboptimal
|
|
||||||
},
|
},
|
||||||
start_layout: image_layout,
|
start_layout: image_layout,
|
||||||
end_layout: image_layout,
|
end_layout: image_layout,
|
||||||
@ -1762,16 +1770,10 @@ impl SyncCommandBufferBuilder {
|
|||||||
image: image_view.image(),
|
image: image_view.image(),
|
||||||
subresource_range: image_view.subresource_range().clone(),
|
subresource_range: image_view.subresource_range().clone(),
|
||||||
memory: PipelineMemoryAccess {
|
memory: PipelineMemoryAccess {
|
||||||
stages: PipelineStages {
|
stages: PipelineStages::ALL_COMMANDS, // TODO: wrong!
|
||||||
all_commands: true,
|
access: AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ
|
||||||
..PipelineStages::empty()
|
| AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE, // TODO: suboptimal
|
||||||
}, // TODO: wrong!
|
exclusive: true, // TODO: suboptimal
|
||||||
access: AccessFlags {
|
|
||||||
depth_stencil_attachment_read: true,
|
|
||||||
depth_stencil_attachment_write: true,
|
|
||||||
..AccessFlags::empty()
|
|
||||||
}, // TODO: suboptimal
|
|
||||||
exclusive: true, // TODO: suboptimal
|
|
||||||
},
|
},
|
||||||
start_layout: image_layout,
|
start_layout: image_layout,
|
||||||
end_layout: image_layout,
|
end_layout: image_layout,
|
||||||
@ -1790,15 +1792,9 @@ impl SyncCommandBufferBuilder {
|
|||||||
image: image_view.image(),
|
image: image_view.image(),
|
||||||
subresource_range: image_view.subresource_range().clone(),
|
subresource_range: image_view.subresource_range().clone(),
|
||||||
memory: PipelineMemoryAccess {
|
memory: PipelineMemoryAccess {
|
||||||
stages: PipelineStages {
|
stages: PipelineStages::ALL_COMMANDS, // TODO: wrong!
|
||||||
all_commands: true,
|
access: AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ
|
||||||
..PipelineStages::empty()
|
| AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE, // TODO: suboptimal
|
||||||
}, // TODO: wrong!
|
|
||||||
access: AccessFlags {
|
|
||||||
depth_stencil_attachment_read: true,
|
|
||||||
depth_stencil_attachment_write: true,
|
|
||||||
..AccessFlags::empty()
|
|
||||||
}, // TODO: suboptimal
|
|
||||||
exclusive: true, // TODO: suboptimal
|
exclusive: true, // TODO: suboptimal
|
||||||
},
|
},
|
||||||
start_layout: image_layout,
|
start_layout: image_layout,
|
||||||
@ -1828,16 +1824,10 @@ impl SyncCommandBufferBuilder {
|
|||||||
image: image_view.image(),
|
image: image_view.image(),
|
||||||
subresource_range: image_view.subresource_range().clone(),
|
subresource_range: image_view.subresource_range().clone(),
|
||||||
memory: PipelineMemoryAccess {
|
memory: PipelineMemoryAccess {
|
||||||
stages: PipelineStages {
|
stages: PipelineStages::ALL_COMMANDS, // TODO: wrong!
|
||||||
all_commands: true,
|
access: AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ
|
||||||
..PipelineStages::empty()
|
| AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE, // TODO: suboptimal
|
||||||
}, // TODO: wrong!
|
exclusive: true, // TODO: suboptimal
|
||||||
access: AccessFlags {
|
|
||||||
depth_stencil_attachment_read: true,
|
|
||||||
depth_stencil_attachment_write: true,
|
|
||||||
..AccessFlags::empty()
|
|
||||||
}, // TODO: suboptimal
|
|
||||||
exclusive: true, // TODO: suboptimal
|
|
||||||
},
|
},
|
||||||
start_layout: image_layout,
|
start_layout: image_layout,
|
||||||
end_layout: image_layout,
|
end_layout: image_layout,
|
||||||
@ -1856,15 +1846,9 @@ impl SyncCommandBufferBuilder {
|
|||||||
image: image_view.image(),
|
image: image_view.image(),
|
||||||
subresource_range: image_view.subresource_range().clone(),
|
subresource_range: image_view.subresource_range().clone(),
|
||||||
memory: PipelineMemoryAccess {
|
memory: PipelineMemoryAccess {
|
||||||
stages: PipelineStages {
|
stages: PipelineStages::ALL_COMMANDS, // TODO: wrong!
|
||||||
all_commands: true,
|
access: AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ
|
||||||
..PipelineStages::empty()
|
| AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE, // TODO: suboptimal
|
||||||
}, // TODO: wrong!
|
|
||||||
access: AccessFlags {
|
|
||||||
depth_stencil_attachment_read: true,
|
|
||||||
depth_stencil_attachment_write: true,
|
|
||||||
..AccessFlags::empty()
|
|
||||||
}, // TODO: suboptimal
|
|
||||||
exclusive: true, // TODO: suboptimal
|
exclusive: true, // TODO: suboptimal
|
||||||
},
|
},
|
||||||
start_layout: image_layout,
|
start_layout: image_layout,
|
||||||
@ -2429,7 +2413,7 @@ impl RenderingAttachmentInfo {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn image_view(image_view: Arc<dyn ImageViewAbstract>) -> Self {
|
pub fn image_view(image_view: Arc<dyn ImageViewAbstract>) -> Self {
|
||||||
let aspects = image_view.format().unwrap().aspects();
|
let aspects = image_view.format().unwrap().aspects();
|
||||||
let image_layout = if aspects.depth || aspects.stencil {
|
let image_layout = if aspects.intersects(ImageAspects::DEPTH | ImageAspects::STENCIL) {
|
||||||
ImageLayout::DepthStencilAttachmentOptimal
|
ImageLayout::DepthStencilAttachmentOptimal
|
||||||
} else {
|
} else {
|
||||||
ImageLayout::ColorAttachmentOptimal
|
ImageLayout::ColorAttachmentOptimal
|
||||||
@ -2473,7 +2457,7 @@ impl RenderingAttachmentResolveInfo {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn image_view(image_view: Arc<dyn ImageViewAbstract>) -> Self {
|
pub fn image_view(image_view: Arc<dyn ImageViewAbstract>) -> Self {
|
||||||
let aspects = image_view.format().unwrap().aspects();
|
let aspects = image_view.format().unwrap().aspects();
|
||||||
let image_layout = if aspects.depth || aspects.stencil {
|
let image_layout = if aspects.intersects(ImageAspects::DEPTH | ImageAspects::STENCIL) {
|
||||||
ImageLayout::DepthStencilAttachmentOptimal
|
ImageLayout::DepthStencilAttachmentOptimal
|
||||||
} else {
|
} else {
|
||||||
ImageLayout::ColorAttachmentOptimal
|
ImageLayout::ColorAttachmentOptimal
|
||||||
|
@ -16,7 +16,7 @@ use crate::{
|
|||||||
AutoCommandBufferBuilder, CommandBufferExecError, CommandBufferInheritanceRenderPassType,
|
AutoCommandBufferBuilder, CommandBufferExecError, CommandBufferInheritanceRenderPassType,
|
||||||
CommandBufferUsage, SecondaryCommandBufferAbstract, SubpassContents,
|
CommandBufferUsage, SecondaryCommandBufferAbstract, SubpassContents,
|
||||||
},
|
},
|
||||||
device::DeviceOwned,
|
device::{DeviceOwned, QueueFlags},
|
||||||
format::Format,
|
format::Format,
|
||||||
image::SampleCount,
|
image::SampleCount,
|
||||||
query::{QueryControlFlags, QueryPipelineStatisticFlags, QueryType},
|
query::{QueryControlFlags, QueryPipelineStatisticFlags, QueryType},
|
||||||
@ -119,9 +119,9 @@ where
|
|||||||
let queue_family_properties = self.queue_family_properties();
|
let queue_family_properties = self.queue_family_properties();
|
||||||
|
|
||||||
// VUID-vkCmdExecuteCommands-commandBuffer-cmdpool
|
// VUID-vkCmdExecuteCommands-commandBuffer-cmdpool
|
||||||
if !(queue_family_properties.queue_flags.transfer
|
if !queue_family_properties
|
||||||
|| queue_family_properties.queue_flags.graphics
|
.queue_flags
|
||||||
|| queue_family_properties.queue_flags.compute)
|
.intersects(QueueFlags::TRANSFER | QueueFlags::GRAPHICS | QueueFlags::COMPUTE)
|
||||||
{
|
{
|
||||||
return Err(ExecuteCommandsError::NotSupportedByQueueFamily);
|
return Err(ExecuteCommandsError::NotSupportedByQueueFamily);
|
||||||
}
|
}
|
||||||
@ -325,7 +325,7 @@ where
|
|||||||
// VUID-vkCmdExecuteCommands-commandBuffer-00101
|
// VUID-vkCmdExecuteCommands-commandBuffer-00101
|
||||||
if !self.query_state.is_empty() && !self.device().enabled_features().inherited_queries {
|
if !self.query_state.is_empty() && !self.device().enabled_features().inherited_queries {
|
||||||
return Err(ExecuteCommandsError::RequirementNotMet {
|
return Err(ExecuteCommandsError::RequirementNotMet {
|
||||||
required_for: "`execute_commands` when a query is active",
|
required_for: "`AutoCommandBufferBuilder::execute_commands` when a query is active",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["inherited_queries"],
|
features: &["inherited_queries"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -126,8 +126,8 @@ impl UnsafeCommandBufferBuilder {
|
|||||||
_ne: _,
|
_ne: _,
|
||||||
} = barrier;
|
} = barrier;
|
||||||
|
|
||||||
debug_assert!(src_stages.supported_access().contains(&src_access));
|
debug_assert!(src_stages.supported_access().contains(src_access));
|
||||||
debug_assert!(dst_stages.supported_access().contains(&dst_access));
|
debug_assert!(dst_stages.supported_access().contains(dst_access));
|
||||||
|
|
||||||
ash::vk::MemoryBarrier2 {
|
ash::vk::MemoryBarrier2 {
|
||||||
src_stage_mask: src_stages.into(),
|
src_stage_mask: src_stages.into(),
|
||||||
@ -153,8 +153,8 @@ impl UnsafeCommandBufferBuilder {
|
|||||||
_ne: _,
|
_ne: _,
|
||||||
} = barrier;
|
} = barrier;
|
||||||
|
|
||||||
debug_assert!(src_stages.supported_access().contains(&src_access));
|
debug_assert!(src_stages.supported_access().contains(src_access));
|
||||||
debug_assert!(dst_stages.supported_access().contains(&dst_access));
|
debug_assert!(dst_stages.supported_access().contains(dst_access));
|
||||||
debug_assert!(!range.is_empty());
|
debug_assert!(!range.is_empty());
|
||||||
debug_assert!(range.end <= buffer.size());
|
debug_assert!(range.end <= buffer.size());
|
||||||
|
|
||||||
@ -195,8 +195,8 @@ impl UnsafeCommandBufferBuilder {
|
|||||||
_ne: _,
|
_ne: _,
|
||||||
} = barrier;
|
} = barrier;
|
||||||
|
|
||||||
debug_assert!(src_stages.supported_access().contains(&src_access));
|
debug_assert!(src_stages.supported_access().contains(src_access));
|
||||||
debug_assert!(dst_stages.supported_access().contains(&dst_access));
|
debug_assert!(dst_stages.supported_access().contains(dst_access));
|
||||||
debug_assert!(!matches!(
|
debug_assert!(!matches!(
|
||||||
new_layout,
|
new_layout,
|
||||||
ImageLayout::Undefined | ImageLayout::Preinitialized
|
ImageLayout::Undefined | ImageLayout::Preinitialized
|
||||||
@ -205,7 +205,7 @@ impl UnsafeCommandBufferBuilder {
|
|||||||
.format()
|
.format()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.aspects()
|
.aspects()
|
||||||
.contains(&subresource_range.aspects));
|
.contains(subresource_range.aspects));
|
||||||
debug_assert!(!subresource_range.mip_levels.is_empty());
|
debug_assert!(!subresource_range.mip_levels.is_empty());
|
||||||
debug_assert!(subresource_range.mip_levels.end <= image.mip_levels());
|
debug_assert!(subresource_range.mip_levels.end <= image.mip_levels());
|
||||||
debug_assert!(!subresource_range.array_layers.is_empty());
|
debug_assert!(!subresource_range.array_layers.is_empty());
|
||||||
@ -272,8 +272,8 @@ impl UnsafeCommandBufferBuilder {
|
|||||||
_ne: _,
|
_ne: _,
|
||||||
} = barrier;
|
} = barrier;
|
||||||
|
|
||||||
debug_assert!(src_stages.supported_access().contains(&src_access));
|
debug_assert!(src_stages.supported_access().contains(src_access));
|
||||||
debug_assert!(dst_stages.supported_access().contains(&dst_access));
|
debug_assert!(dst_stages.supported_access().contains(dst_access));
|
||||||
|
|
||||||
src_stage_mask |= src_stages.into();
|
src_stage_mask |= src_stages.into();
|
||||||
dst_stage_mask |= dst_stages.into();
|
dst_stage_mask |= dst_stages.into();
|
||||||
@ -300,8 +300,8 @@ impl UnsafeCommandBufferBuilder {
|
|||||||
_ne: _,
|
_ne: _,
|
||||||
} = barrier;
|
} = barrier;
|
||||||
|
|
||||||
debug_assert!(src_stages.supported_access().contains(&src_access));
|
debug_assert!(src_stages.supported_access().contains(src_access));
|
||||||
debug_assert!(dst_stages.supported_access().contains(&dst_access));
|
debug_assert!(dst_stages.supported_access().contains(dst_access));
|
||||||
debug_assert!(!range.is_empty());
|
debug_assert!(!range.is_empty());
|
||||||
debug_assert!(range.end <= buffer.size());
|
debug_assert!(range.end <= buffer.size());
|
||||||
|
|
||||||
@ -343,8 +343,8 @@ impl UnsafeCommandBufferBuilder {
|
|||||||
_ne: _,
|
_ne: _,
|
||||||
} = barrier;
|
} = barrier;
|
||||||
|
|
||||||
debug_assert!(src_stages.supported_access().contains(&src_access));
|
debug_assert!(src_stages.supported_access().contains(src_access));
|
||||||
debug_assert!(dst_stages.supported_access().contains(&dst_access));
|
debug_assert!(dst_stages.supported_access().contains(dst_access));
|
||||||
debug_assert!(!matches!(
|
debug_assert!(!matches!(
|
||||||
new_layout,
|
new_layout,
|
||||||
ImageLayout::Undefined | ImageLayout::Preinitialized
|
ImageLayout::Undefined | ImageLayout::Preinitialized
|
||||||
@ -353,7 +353,7 @@ impl UnsafeCommandBufferBuilder {
|
|||||||
.format()
|
.format()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.aspects()
|
.aspects()
|
||||||
.contains(&subresource_range.aspects));
|
.contains(subresource_range.aspects));
|
||||||
debug_assert!(!subresource_range.mip_levels.is_empty());
|
debug_assert!(!subresource_range.mip_levels.is_empty());
|
||||||
debug_assert!(subresource_range.mip_levels.end <= image.mip_levels());
|
debug_assert!(subresource_range.mip_levels.end <= image.mip_levels());
|
||||||
debug_assert!(!subresource_range.array_layers.is_empty());
|
debug_assert!(!subresource_range.array_layers.is_empty());
|
||||||
@ -895,7 +895,7 @@ impl UnsafeCommandBufferBuilder {
|
|||||||
/// Calls `vkCmdResetEvent` on the builder.
|
/// Calls `vkCmdResetEvent` on the builder.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn reset_event(&mut self, event: &Event, stages: PipelineStages) {
|
pub unsafe fn reset_event(&mut self, event: &Event, stages: PipelineStages) {
|
||||||
debug_assert!(!stages.host);
|
debug_assert!(!stages.intersects(PipelineStages::HOST));
|
||||||
debug_assert_ne!(stages, PipelineStages::empty());
|
debug_assert_ne!(stages, PipelineStages::empty());
|
||||||
|
|
||||||
let fns = self.device.fns();
|
let fns = self.device.fns();
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -169,8 +169,9 @@ pub struct DispatchIndirectCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vulkan_enum! {
|
vulkan_enum! {
|
||||||
/// Describes what a subpass in a command buffer will contain.
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
|
|
||||||
|
/// Describes what a subpass in a command buffer will contain.
|
||||||
SubpassContents = SubpassContents(i32);
|
SubpassContents = SubpassContents(i32);
|
||||||
|
|
||||||
/// The subpass will only directly contain commands.
|
/// The subpass will only directly contain commands.
|
||||||
@ -229,10 +230,12 @@ pub struct CommandBufferInheritanceInfo {
|
|||||||
/// Which pipeline statistics queries are allowed to be active on the primary command buffer
|
/// Which pipeline statistics queries are allowed to be active on the primary command buffer
|
||||||
/// when this secondary command buffer is executed.
|
/// when this secondary command buffer is executed.
|
||||||
///
|
///
|
||||||
/// The `pipeline_statistics_query` feature must be enabled if any of the flags of this value
|
/// If this value is not empty, the [`pipeline_statistics_query`] feature must be enabled on
|
||||||
/// are set.
|
/// the device.
|
||||||
///
|
///
|
||||||
/// The default value is [`QueryPipelineStatisticFlags::empty()`].
|
/// The default value is [`QueryPipelineStatisticFlags::empty()`].
|
||||||
|
///
|
||||||
|
/// [`pipeline_statistics_query`]: crate::device::Features::pipeline_statistics_query
|
||||||
pub query_statistics_flags: QueryPipelineStatisticFlags,
|
pub query_statistics_flags: QueryPipelineStatisticFlags,
|
||||||
|
|
||||||
pub _ne: crate::NonExhaustive,
|
pub _ne: crate::NonExhaustive,
|
||||||
@ -326,10 +329,11 @@ pub struct CommandBufferInheritanceRenderingInfo {
|
|||||||
/// indices that are rendered to. The value is a bitmask, so that that for example `0b11` will
|
/// indices that are rendered to. The value is a bitmask, so that that for example `0b11` will
|
||||||
/// draw to the first two views and `0b101` will draw to the first and third view.
|
/// draw to the first two views and `0b101` will draw to the first and third view.
|
||||||
///
|
///
|
||||||
/// If set to a nonzero value, the [`multiview`](crate::device::Features::multiview) feature
|
/// If set to a nonzero value, then the [`multiview`] feature must be enabled on the device.
|
||||||
/// must be enabled on the device.
|
|
||||||
///
|
///
|
||||||
/// The default value is `0`.
|
/// The default value is `0`.
|
||||||
|
///
|
||||||
|
/// [`multiview`]: crate::device::Features::multiview
|
||||||
pub view_mask: u32,
|
pub view_mask: u32,
|
||||||
|
|
||||||
/// The formats of the color attachments that will be used during rendering.
|
/// The formats of the color attachments that will be used during rendering.
|
||||||
@ -449,11 +453,13 @@ pub struct SemaphoreSubmitInfo {
|
|||||||
/// For a semaphore signal operation, specifies the pipeline stages in the first synchronization
|
/// For a semaphore signal operation, specifies the pipeline stages in the first synchronization
|
||||||
/// scope: stages of queue operations preceding the signal operation that must complete before
|
/// scope: stages of queue operations preceding the signal operation that must complete before
|
||||||
/// the semaphore is signalled.
|
/// the semaphore is signalled.
|
||||||
/// If not set to `all_commands` only, the
|
/// If this value does not equal [`ALL_COMMANDS`], then the [`synchronization2`] feature must
|
||||||
/// [`synchronization2`](crate::device::Features::synchronization2) feature must be enabled
|
/// be enabled on the device.
|
||||||
/// on the device.
|
|
||||||
///
|
///
|
||||||
/// The default value has only `all_commands` set.
|
/// The default value is [`ALL_COMMANDS`].
|
||||||
|
///
|
||||||
|
/// [`ALL_COMMANDS`]: PipelineStages::ALL_COMMANDS
|
||||||
|
/// [`synchronization2`]: crate::device::Features::synchronization2
|
||||||
pub stages: PipelineStages,
|
pub stages: PipelineStages,
|
||||||
|
|
||||||
pub _ne: crate::NonExhaustive,
|
pub _ne: crate::NonExhaustive,
|
||||||
@ -465,10 +471,7 @@ impl SemaphoreSubmitInfo {
|
|||||||
pub fn semaphore(semaphore: Arc<Semaphore>) -> Self {
|
pub fn semaphore(semaphore: Arc<Semaphore>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
semaphore,
|
semaphore,
|
||||||
stages: PipelineStages {
|
stages: PipelineStages::ALL_COMMANDS,
|
||||||
all_commands: true,
|
|
||||||
..PipelineStages::empty()
|
|
||||||
},
|
|
||||||
_ne: crate::NonExhaustive(()),
|
_ne: crate::NonExhaustive(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -276,7 +276,7 @@ impl CommandPool {
|
|||||||
|| self.device.enabled_extensions().khr_maintenance1)
|
|| self.device.enabled_extensions().khr_maintenance1)
|
||||||
{
|
{
|
||||||
return Err(CommandPoolTrimError::RequirementNotMet {
|
return Err(CommandPoolTrimError::RequirementNotMet {
|
||||||
required_for: "`trim`",
|
required_for: "`CommandPool::trim`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
api_version: Some(Version::V1_1),
|
api_version: Some(Version::V1_1),
|
||||||
device_extensions: &["khr_maintenance1"],
|
device_extensions: &["khr_maintenance1"],
|
||||||
|
@ -205,7 +205,7 @@ impl SyncCommandBufferBuilder {
|
|||||||
ref range,
|
ref range,
|
||||||
ref memory,
|
ref memory,
|
||||||
} => {
|
} => {
|
||||||
debug_assert!(memory.stages.supported_access().contains(&memory.access));
|
debug_assert!(memory.stages.supported_access().contains(memory.access));
|
||||||
|
|
||||||
if let Some(conflicting_use) =
|
if let Some(conflicting_use) =
|
||||||
self.find_buffer_conflict(buffer, range.clone(), memory)
|
self.find_buffer_conflict(buffer, range.clone(), memory)
|
||||||
@ -226,7 +226,7 @@ impl SyncCommandBufferBuilder {
|
|||||||
end_layout,
|
end_layout,
|
||||||
} => {
|
} => {
|
||||||
debug_assert!(memory.exclusive || start_layout == end_layout);
|
debug_assert!(memory.exclusive || start_layout == end_layout);
|
||||||
debug_assert!(memory.stages.supported_access().contains(&memory.access));
|
debug_assert!(memory.stages.supported_access().contains(memory.access));
|
||||||
debug_assert!(end_layout != ImageLayout::Undefined);
|
debug_assert!(end_layout != ImageLayout::Undefined);
|
||||||
debug_assert!(end_layout != ImageLayout::Preinitialized);
|
debug_assert!(end_layout != ImageLayout::Preinitialized);
|
||||||
|
|
||||||
@ -453,24 +453,10 @@ impl SyncCommandBufferBuilder {
|
|||||||
// will come before them, it's the only thing that works for now.
|
// will come before them, it's the only thing that works for now.
|
||||||
// TODO: come up with something better
|
// TODO: come up with something better
|
||||||
let barrier = BufferMemoryBarrier {
|
let barrier = BufferMemoryBarrier {
|
||||||
src_stages: PipelineStages {
|
src_stages: PipelineStages::ALL_COMMANDS,
|
||||||
all_commands: true,
|
src_access: AccessFlags::MEMORY_READ | AccessFlags::MEMORY_WRITE,
|
||||||
..PipelineStages::empty()
|
dst_stages: PipelineStages::ALL_COMMANDS,
|
||||||
},
|
dst_access: AccessFlags::MEMORY_READ | AccessFlags::MEMORY_WRITE,
|
||||||
src_access: AccessFlags {
|
|
||||||
memory_read: true,
|
|
||||||
memory_write: true,
|
|
||||||
..AccessFlags::empty()
|
|
||||||
},
|
|
||||||
dst_stages: PipelineStages {
|
|
||||||
all_commands: true,
|
|
||||||
..PipelineStages::empty()
|
|
||||||
},
|
|
||||||
dst_access: AccessFlags {
|
|
||||||
memory_read: true,
|
|
||||||
memory_write: true,
|
|
||||||
..AccessFlags::empty()
|
|
||||||
},
|
|
||||||
range: range.clone(),
|
range: range.clone(),
|
||||||
..BufferMemoryBarrier::buffer(inner.buffer.clone())
|
..BufferMemoryBarrier::buffer(inner.buffer.clone())
|
||||||
};
|
};
|
||||||
@ -644,24 +630,10 @@ impl SyncCommandBufferBuilder {
|
|||||||
// will come before them, it's the only thing that works for now.
|
// will come before them, it's the only thing that works for now.
|
||||||
// TODO: come up with something better
|
// TODO: come up with something better
|
||||||
let mut barrier = ImageMemoryBarrier {
|
let mut barrier = ImageMemoryBarrier {
|
||||||
src_stages: PipelineStages {
|
src_stages: PipelineStages::ALL_COMMANDS,
|
||||||
all_commands: true,
|
src_access: AccessFlags::MEMORY_READ | AccessFlags::MEMORY_WRITE,
|
||||||
..PipelineStages::empty()
|
dst_stages: PipelineStages::ALL_COMMANDS,
|
||||||
},
|
dst_access: AccessFlags::MEMORY_READ | AccessFlags::MEMORY_WRITE,
|
||||||
src_access: AccessFlags {
|
|
||||||
memory_read: true,
|
|
||||||
memory_write: true,
|
|
||||||
..AccessFlags::empty()
|
|
||||||
},
|
|
||||||
dst_stages: PipelineStages {
|
|
||||||
all_commands: true,
|
|
||||||
..PipelineStages::empty()
|
|
||||||
},
|
|
||||||
dst_access: AccessFlags {
|
|
||||||
memory_read: true,
|
|
||||||
memory_write: true,
|
|
||||||
..AccessFlags::empty()
|
|
||||||
},
|
|
||||||
old_layout: state.initial_layout,
|
old_layout: state.initial_layout,
|
||||||
new_layout: state.initial_layout,
|
new_layout: state.initial_layout,
|
||||||
subresource_range: inner.image.range_to_subresources(range.clone()),
|
subresource_range: inner.image.range_to_subresources(range.clone()),
|
||||||
@ -812,10 +784,7 @@ impl SyncCommandBufferBuilder {
|
|||||||
.push(ImageMemoryBarrier {
|
.push(ImageMemoryBarrier {
|
||||||
src_stages: state.memory.stages,
|
src_stages: state.memory.stages,
|
||||||
src_access: state.memory.access,
|
src_access: state.memory.access,
|
||||||
dst_stages: PipelineStages {
|
dst_stages: PipelineStages::TOP_OF_PIPE,
|
||||||
top_of_pipe: true,
|
|
||||||
..PipelineStages::empty()
|
|
||||||
},
|
|
||||||
dst_access: AccessFlags::empty(),
|
dst_access: AccessFlags::empty(),
|
||||||
old_layout: state.current_layout,
|
old_layout: state.current_layout,
|
||||||
new_layout: state.final_layout,
|
new_layout: state.final_layout,
|
||||||
|
@ -427,10 +427,7 @@ mod tests {
|
|||||||
let buffer = DeviceLocalBuffer::from_data(
|
let buffer = DeviceLocalBuffer::from_data(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
0u32,
|
0u32,
|
||||||
BufferUsage {
|
BufferUsage::TRANSFER_DST,
|
||||||
transfer_dst: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
&mut cbb,
|
&mut cbb,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -542,10 +539,7 @@ mod tests {
|
|||||||
let memory_allocator = StandardMemoryAllocator::new_default(device);
|
let memory_allocator = StandardMemoryAllocator::new_default(device);
|
||||||
let buf = CpuAccessibleBuffer::from_data(
|
let buf = CpuAccessibleBuffer::from_data(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::VERTEX_BUFFER,
|
||||||
vertex_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
0u32,
|
0u32,
|
||||||
)
|
)
|
||||||
|
@ -20,6 +20,7 @@ use crate::{
|
|||||||
CommandBufferInheritanceRenderingInfo,
|
CommandBufferInheritanceRenderingInfo,
|
||||||
},
|
},
|
||||||
device::{Device, DeviceOwned},
|
device::{Device, DeviceOwned},
|
||||||
|
query::QueryControlFlags,
|
||||||
OomError, VulkanError, VulkanObject,
|
OomError, VulkanError, VulkanObject,
|
||||||
};
|
};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
@ -104,7 +105,7 @@ impl UnsafeCommandBufferBuilder {
|
|||||||
if let Some(flags) = occlusion_query {
|
if let Some(flags) = occlusion_query {
|
||||||
inheritance_info_vk.occlusion_query_enable = ash::vk::TRUE;
|
inheritance_info_vk.occlusion_query_enable = ash::vk::TRUE;
|
||||||
|
|
||||||
if flags.precise {
|
if flags.intersects(QueryControlFlags::PRECISE) {
|
||||||
inheritance_info_vk.query_flags = ash::vk::QueryControlFlags::PRECISE;
|
inheritance_info_vk.query_flags = ash::vk::QueryControlFlags::PRECISE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -335,11 +335,8 @@ where
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|semaphore| {
|
.map(|semaphore| {
|
||||||
SemaphoreSubmitInfo {
|
SemaphoreSubmitInfo {
|
||||||
stages: PipelineStages {
|
// TODO: correct stages ; hard
|
||||||
// TODO: correct stages ; hard
|
stages: PipelineStages::ALL_COMMANDS,
|
||||||
all_commands: true,
|
|
||||||
..PipelineStages::empty()
|
|
||||||
},
|
|
||||||
..SemaphoreSubmitInfo::semaphore(semaphore)
|
..SemaphoreSubmitInfo::semaphore(semaphore)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -221,7 +221,8 @@ impl DescriptorSetLayout {
|
|||||||
.descriptor_binding_variable_descriptor_count
|
.descriptor_binding_variable_descriptor_count
|
||||||
{
|
{
|
||||||
return Err(DescriptorSetLayoutCreationError::RequirementNotMet {
|
return Err(DescriptorSetLayoutCreationError::RequirementNotMet {
|
||||||
required_for: "`create_info.bindings` has an element where `variable_descriptor_count` is set",
|
required_for: "`create_info.bindings` has an element where \
|
||||||
|
`variable_descriptor_count` is set",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["descriptor_binding_variable_descriptor_count"],
|
features: &["descriptor_binding_variable_descriptor_count"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -756,7 +757,7 @@ impl DescriptorSetLayoutBinding {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !self.stages.contains(&stages) {
|
if !self.stages.contains(stages) {
|
||||||
return Err(DescriptorRequirementsNotMet::ShaderStages {
|
return Err(DescriptorRequirementsNotMet::ShaderStages {
|
||||||
required: stages,
|
required: stages,
|
||||||
obtained: self.stages,
|
obtained: self.stages,
|
||||||
@ -824,8 +825,9 @@ impl Display for DescriptorRequirementsNotMet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vulkan_enum! {
|
vulkan_enum! {
|
||||||
/// Describes what kind of resource may later be bound to a descriptor.
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
|
|
||||||
|
/// Describes what kind of resource may later be bound to a descriptor.
|
||||||
DescriptorType = DescriptorType(i32);
|
DescriptorType = DescriptorType(i32);
|
||||||
|
|
||||||
/// Describes how a `SampledImage` descriptor should be read.
|
/// Describes how a `SampledImage` descriptor should be read.
|
||||||
|
@ -9,9 +9,9 @@
|
|||||||
|
|
||||||
use super::layout::{DescriptorSetLayout, DescriptorSetLayoutBinding, DescriptorType};
|
use super::layout::{DescriptorSetLayout, DescriptorSetLayoutBinding, DescriptorType};
|
||||||
use crate::{
|
use crate::{
|
||||||
buffer::{view::BufferViewAbstract, BufferAccess, BufferInner},
|
buffer::{view::BufferViewAbstract, BufferAccess, BufferInner, BufferUsage},
|
||||||
device::DeviceOwned,
|
device::DeviceOwned,
|
||||||
image::{view::ImageViewType, ImageType, ImageViewAbstract},
|
image::{view::ImageViewType, ImageAspects, ImageType, ImageUsage, ImageViewAbstract},
|
||||||
sampler::{Sampler, SamplerImageViewIncompatibleError},
|
sampler::{Sampler, SamplerImageViewIncompatibleError},
|
||||||
DeviceSize, RequiresOneOf, VulkanObject,
|
DeviceSize, RequiresOneOf, VulkanObject,
|
||||||
};
|
};
|
||||||
@ -425,7 +425,7 @@ pub(crate) fn check_descriptor_write<'a>(
|
|||||||
for (index, buffer) in elements.iter().enumerate() {
|
for (index, buffer) in elements.iter().enumerate() {
|
||||||
assert_eq!(device, buffer.device());
|
assert_eq!(device, buffer.device());
|
||||||
|
|
||||||
if !buffer.inner().buffer.usage().storage_buffer {
|
if !buffer.usage().intersects(BufferUsage::STORAGE_BUFFER) {
|
||||||
return Err(DescriptorSetUpdateError::MissingUsage {
|
return Err(DescriptorSetUpdateError::MissingUsage {
|
||||||
binding: write.binding(),
|
binding: write.binding(),
|
||||||
index: descriptor_range_start + index as u32,
|
index: descriptor_range_start + index as u32,
|
||||||
@ -438,7 +438,7 @@ pub(crate) fn check_descriptor_write<'a>(
|
|||||||
for (index, buffer) in elements.iter().enumerate() {
|
for (index, buffer) in elements.iter().enumerate() {
|
||||||
assert_eq!(device, buffer.device());
|
assert_eq!(device, buffer.device());
|
||||||
|
|
||||||
if !buffer.inner().buffer.usage().uniform_buffer {
|
if !buffer.usage().intersects(BufferUsage::UNIFORM_BUFFER) {
|
||||||
return Err(DescriptorSetUpdateError::MissingUsage {
|
return Err(DescriptorSetUpdateError::MissingUsage {
|
||||||
binding: write.binding(),
|
binding: write.binding(),
|
||||||
index: descriptor_range_start + index as u32,
|
index: descriptor_range_start + index as u32,
|
||||||
@ -474,10 +474,8 @@ pub(crate) fn check_descriptor_write<'a>(
|
|||||||
// TODO: storage_texel_buffer_atomic
|
// TODO: storage_texel_buffer_atomic
|
||||||
if !buffer_view
|
if !buffer_view
|
||||||
.buffer()
|
.buffer()
|
||||||
.inner()
|
|
||||||
.buffer
|
|
||||||
.usage()
|
.usage()
|
||||||
.storage_texel_buffer
|
.intersects(BufferUsage::STORAGE_TEXEL_BUFFER)
|
||||||
{
|
{
|
||||||
return Err(DescriptorSetUpdateError::MissingUsage {
|
return Err(DescriptorSetUpdateError::MissingUsage {
|
||||||
binding: write.binding(),
|
binding: write.binding(),
|
||||||
@ -493,10 +491,8 @@ pub(crate) fn check_descriptor_write<'a>(
|
|||||||
|
|
||||||
if !buffer_view
|
if !buffer_view
|
||||||
.buffer()
|
.buffer()
|
||||||
.inner()
|
|
||||||
.buffer
|
|
||||||
.usage()
|
.usage()
|
||||||
.uniform_texel_buffer
|
.intersects(BufferUsage::UNIFORM_TEXEL_BUFFER)
|
||||||
{
|
{
|
||||||
return Err(DescriptorSetUpdateError::MissingUsage {
|
return Err(DescriptorSetUpdateError::MissingUsage {
|
||||||
binding: write.binding(),
|
binding: write.binding(),
|
||||||
@ -526,7 +522,7 @@ pub(crate) fn check_descriptor_write<'a>(
|
|||||||
assert_eq!(device, image_view.device());
|
assert_eq!(device, image_view.device());
|
||||||
|
|
||||||
// VUID-VkWriteDescriptorSet-descriptorType-00337
|
// VUID-VkWriteDescriptorSet-descriptorType-00337
|
||||||
if !image_view.usage().sampled {
|
if !image_view.usage().intersects(ImageUsage::SAMPLED) {
|
||||||
return Err(DescriptorSetUpdateError::MissingUsage {
|
return Err(DescriptorSetUpdateError::MissingUsage {
|
||||||
binding: write.binding(),
|
binding: write.binding(),
|
||||||
index: descriptor_range_start + index as u32,
|
index: descriptor_range_start + index as u32,
|
||||||
@ -548,8 +544,10 @@ pub(crate) fn check_descriptor_write<'a>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VUID-VkDescriptorImageInfo-imageView-01976
|
// VUID-VkDescriptorImageInfo-imageView-01976
|
||||||
if image_view.subresource_range().aspects.depth
|
if image_view
|
||||||
&& image_view.subresource_range().aspects.stencil
|
.subresource_range()
|
||||||
|
.aspects
|
||||||
|
.contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
|
||||||
{
|
{
|
||||||
return Err(DescriptorSetUpdateError::ImageViewDepthAndStencil {
|
return Err(DescriptorSetUpdateError::ImageViewDepthAndStencil {
|
||||||
binding: write.binding(),
|
binding: write.binding(),
|
||||||
@ -571,7 +569,7 @@ pub(crate) fn check_descriptor_write<'a>(
|
|||||||
assert_eq!(device, image_view.device());
|
assert_eq!(device, image_view.device());
|
||||||
|
|
||||||
// VUID-VkWriteDescriptorSet-descriptorType-00337
|
// VUID-VkWriteDescriptorSet-descriptorType-00337
|
||||||
if !image_view.usage().sampled {
|
if !image_view.usage().intersects(ImageUsage::SAMPLED) {
|
||||||
return Err(DescriptorSetUpdateError::MissingUsage {
|
return Err(DescriptorSetUpdateError::MissingUsage {
|
||||||
binding: write.binding(),
|
binding: write.binding(),
|
||||||
index: descriptor_range_start + index as u32,
|
index: descriptor_range_start + index as u32,
|
||||||
@ -593,8 +591,10 @@ pub(crate) fn check_descriptor_write<'a>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VUID-VkDescriptorImageInfo-imageView-01976
|
// VUID-VkDescriptorImageInfo-imageView-01976
|
||||||
if image_view.subresource_range().aspects.depth
|
if image_view
|
||||||
&& image_view.subresource_range().aspects.stencil
|
.subresource_range()
|
||||||
|
.aspects
|
||||||
|
.contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
|
||||||
{
|
{
|
||||||
return Err(DescriptorSetUpdateError::ImageViewDepthAndStencil {
|
return Err(DescriptorSetUpdateError::ImageViewDepthAndStencil {
|
||||||
binding: write.binding(),
|
binding: write.binding(),
|
||||||
@ -618,7 +618,7 @@ pub(crate) fn check_descriptor_write<'a>(
|
|||||||
assert_eq!(device, image_view.device());
|
assert_eq!(device, image_view.device());
|
||||||
|
|
||||||
// VUID-VkWriteDescriptorSet-descriptorType-00339
|
// VUID-VkWriteDescriptorSet-descriptorType-00339
|
||||||
if !image_view.usage().storage {
|
if !image_view.usage().intersects(ImageUsage::STORAGE) {
|
||||||
return Err(DescriptorSetUpdateError::MissingUsage {
|
return Err(DescriptorSetUpdateError::MissingUsage {
|
||||||
binding: write.binding(),
|
binding: write.binding(),
|
||||||
index: descriptor_range_start + index as u32,
|
index: descriptor_range_start + index as u32,
|
||||||
@ -640,8 +640,10 @@ pub(crate) fn check_descriptor_write<'a>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VUID-VkDescriptorImageInfo-imageView-01976
|
// VUID-VkDescriptorImageInfo-imageView-01976
|
||||||
if image_view.subresource_range().aspects.depth
|
if image_view
|
||||||
&& image_view.subresource_range().aspects.stencil
|
.subresource_range()
|
||||||
|
.aspects
|
||||||
|
.contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
|
||||||
{
|
{
|
||||||
return Err(DescriptorSetUpdateError::ImageViewDepthAndStencil {
|
return Err(DescriptorSetUpdateError::ImageViewDepthAndStencil {
|
||||||
binding: write.binding(),
|
binding: write.binding(),
|
||||||
@ -673,7 +675,7 @@ pub(crate) fn check_descriptor_write<'a>(
|
|||||||
assert_eq!(device, image_view.device());
|
assert_eq!(device, image_view.device());
|
||||||
|
|
||||||
// VUID-VkWriteDescriptorSet-descriptorType-00338
|
// VUID-VkWriteDescriptorSet-descriptorType-00338
|
||||||
if !image_view.usage().input_attachment {
|
if !image_view.usage().intersects(ImageUsage::INPUT_ATTACHMENT) {
|
||||||
return Err(DescriptorSetUpdateError::MissingUsage {
|
return Err(DescriptorSetUpdateError::MissingUsage {
|
||||||
binding: write.binding(),
|
binding: write.binding(),
|
||||||
index: descriptor_range_start + index as u32,
|
index: descriptor_range_start + index as u32,
|
||||||
@ -695,8 +697,10 @@ pub(crate) fn check_descriptor_write<'a>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VUID-VkDescriptorImageInfo-imageView-01976
|
// VUID-VkDescriptorImageInfo-imageView-01976
|
||||||
if image_view.subresource_range().aspects.depth
|
if image_view
|
||||||
&& image_view.subresource_range().aspects.stencil
|
.subresource_range()
|
||||||
|
.aspects
|
||||||
|
.contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
|
||||||
{
|
{
|
||||||
return Err(DescriptorSetUpdateError::ImageViewDepthAndStencil {
|
return Err(DescriptorSetUpdateError::ImageViewDepthAndStencil {
|
||||||
binding: write.binding(),
|
binding: write.binding(),
|
||||||
@ -752,7 +756,7 @@ pub(crate) fn check_descriptor_write<'a>(
|
|||||||
assert_eq!(device, sampler.device());
|
assert_eq!(device, sampler.device());
|
||||||
|
|
||||||
// VUID-VkWriteDescriptorSet-descriptorType-00337
|
// VUID-VkWriteDescriptorSet-descriptorType-00337
|
||||||
if !image_view.usage().sampled {
|
if !image_view.usage().intersects(ImageUsage::SAMPLED) {
|
||||||
return Err(DescriptorSetUpdateError::MissingUsage {
|
return Err(DescriptorSetUpdateError::MissingUsage {
|
||||||
binding: write.binding(),
|
binding: write.binding(),
|
||||||
index: descriptor_range_start + index as u32,
|
index: descriptor_range_start + index as u32,
|
||||||
@ -774,8 +778,10 @@ pub(crate) fn check_descriptor_write<'a>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VUID-VkDescriptorImageInfo-imageView-01976
|
// VUID-VkDescriptorImageInfo-imageView-01976
|
||||||
if image_view.subresource_range().aspects.depth
|
if image_view
|
||||||
&& image_view.subresource_range().aspects.stencil
|
.subresource_range()
|
||||||
|
.aspects
|
||||||
|
.contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
|
||||||
{
|
{
|
||||||
return Err(DescriptorSetUpdateError::ImageViewDepthAndStencil {
|
return Err(DescriptorSetUpdateError::ImageViewDepthAndStencil {
|
||||||
binding: write.binding(),
|
binding: write.binding(),
|
||||||
|
@ -14,15 +14,15 @@ use crate::{
|
|||||||
device::{properties::Properties, DeviceExtensions, Features, FeaturesFfi, PropertiesFfi},
|
device::{properties::Properties, DeviceExtensions, Features, FeaturesFfi, PropertiesFfi},
|
||||||
format::{Format, FormatProperties},
|
format::{Format, FormatProperties},
|
||||||
image::{
|
image::{
|
||||||
ImageFormatInfo, ImageFormatProperties, ImageUsage, SparseImageFormatInfo,
|
ImageAspects, ImageFormatInfo, ImageFormatProperties, ImageUsage, SparseImageFormatInfo,
|
||||||
SparseImageFormatProperties,
|
SparseImageFormatProperties,
|
||||||
},
|
},
|
||||||
instance::Instance,
|
instance::Instance,
|
||||||
macros::{vulkan_bitflags, vulkan_enum},
|
macros::{vulkan_bitflags, vulkan_enum},
|
||||||
memory::MemoryProperties,
|
memory::MemoryProperties,
|
||||||
swapchain::{
|
swapchain::{
|
||||||
ColorSpace, FullScreenExclusive, PresentMode, SupportedSurfaceTransforms, Surface,
|
ColorSpace, FullScreenExclusive, PresentMode, Surface, SurfaceApi, SurfaceCapabilities,
|
||||||
SurfaceApi, SurfaceCapabilities, SurfaceInfo,
|
SurfaceInfo, SurfaceTransforms,
|
||||||
},
|
},
|
||||||
sync::{
|
sync::{
|
||||||
ExternalFenceInfo, ExternalFenceProperties, ExternalSemaphoreInfo,
|
ExternalFenceInfo, ExternalFenceProperties, ExternalSemaphoreInfo,
|
||||||
@ -442,7 +442,7 @@ impl PhysicalDevice {
|
|||||||
) -> Result<(), PhysicalDeviceError> {
|
) -> Result<(), PhysicalDeviceError> {
|
||||||
if !self.instance.enabled_extensions().ext_directfb_surface {
|
if !self.instance.enabled_extensions().ext_directfb_surface {
|
||||||
return Err(PhysicalDeviceError::RequirementNotMet {
|
return Err(PhysicalDeviceError::RequirementNotMet {
|
||||||
required_for: "`directfb_presentation_support`",
|
required_for: "`PhysicalDevice::directfb_presentation_support`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
instance_extensions: &["ext_directfb_surface"],
|
instance_extensions: &["ext_directfb_surface"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -510,7 +510,7 @@ impl PhysicalDevice {
|
|||||||
.khr_external_memory_capabilities)
|
.khr_external_memory_capabilities)
|
||||||
{
|
{
|
||||||
return Err(PhysicalDeviceError::RequirementNotMet {
|
return Err(PhysicalDeviceError::RequirementNotMet {
|
||||||
required_for: "`external_buffer_properties`",
|
required_for: "`PhysicalDevice::external_buffer_properties`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
api_version: Some(Version::V1_1),
|
api_version: Some(Version::V1_1),
|
||||||
instance_extensions: &["khr_external_memory_capabilities"],
|
instance_extensions: &["khr_external_memory_capabilities"],
|
||||||
@ -623,7 +623,7 @@ impl PhysicalDevice {
|
|||||||
.khr_external_fence_capabilities)
|
.khr_external_fence_capabilities)
|
||||||
{
|
{
|
||||||
return Err(PhysicalDeviceError::RequirementNotMet {
|
return Err(PhysicalDeviceError::RequirementNotMet {
|
||||||
required_for: "`external_fence_properties`",
|
required_for: "`PhysicalDevice::external_fence_properties`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
api_version: Some(Version::V1_1),
|
api_version: Some(Version::V1_1),
|
||||||
instance_extensions: &["khr_external_fence_capabilities"],
|
instance_extensions: &["khr_external_fence_capabilities"],
|
||||||
@ -731,7 +731,7 @@ impl PhysicalDevice {
|
|||||||
.khr_external_semaphore_capabilities)
|
.khr_external_semaphore_capabilities)
|
||||||
{
|
{
|
||||||
return Err(PhysicalDeviceError::RequirementNotMet {
|
return Err(PhysicalDeviceError::RequirementNotMet {
|
||||||
required_for: "`external_semaphore_properties`",
|
required_for: "`PhysicalDevice::external_semaphore_properties`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
api_version: Some(Version::V1_1),
|
api_version: Some(Version::V1_1),
|
||||||
instance_extensions: &["khr_external_semaphore_capabilities"],
|
instance_extensions: &["khr_external_semaphore_capabilities"],
|
||||||
@ -941,13 +941,14 @@ impl PhysicalDevice {
|
|||||||
let format = format.unwrap();
|
let format = format.unwrap();
|
||||||
let aspects = format.aspects();
|
let aspects = format.aspects();
|
||||||
|
|
||||||
let has_separate_stencil_usage =
|
let has_separate_stencil_usage = if stencil_usage.is_empty()
|
||||||
if stencil_usage.is_empty() || !(aspects.depth && aspects.stencil) {
|
|| !aspects.contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
|
||||||
stencil_usage = usage;
|
{
|
||||||
false
|
stencil_usage = usage;
|
||||||
} else {
|
false
|
||||||
stencil_usage == usage
|
} else {
|
||||||
};
|
stencil_usage == usage
|
||||||
|
};
|
||||||
|
|
||||||
// VUID-VkPhysicalDeviceImageFormatInfo2-format-parameter
|
// VUID-VkPhysicalDeviceImageFormatInfo2-format-parameter
|
||||||
format.validate_physical_device(self)?;
|
format.validate_physical_device(self)?;
|
||||||
@ -969,7 +970,8 @@ impl PhysicalDevice {
|
|||||||
|| self.supported_extensions().ext_separate_stencil_usage)
|
|| self.supported_extensions().ext_separate_stencil_usage)
|
||||||
{
|
{
|
||||||
return Err(PhysicalDeviceError::RequirementNotMet {
|
return Err(PhysicalDeviceError::RequirementNotMet {
|
||||||
required_for: "`image_format_info.stencil_usage` is `Some` and `image_format_info.format` has both a depth and a stencil aspect",
|
required_for: "`image_format_info.stencil_usage` is `Some` and \
|
||||||
|
`image_format_info.format` has both a depth and a stencil aspect",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
api_version: Some(Version::V1_2),
|
api_version: Some(Version::V1_2),
|
||||||
device_extensions: &["ext_separate_stencil_usage"],
|
device_extensions: &["ext_separate_stencil_usage"],
|
||||||
@ -1040,7 +1042,9 @@ impl PhysicalDevice {
|
|||||||
|
|
||||||
let aspects = format.unwrap().aspects();
|
let aspects = format.unwrap().aspects();
|
||||||
|
|
||||||
if stencil_usage.is_empty() || !(aspects.depth && aspects.stencil) {
|
if stencil_usage.is_empty()
|
||||||
|
|| !aspects.contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
|
||||||
|
{
|
||||||
*stencil_usage = *usage;
|
*stencil_usage = *usage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1213,7 +1217,7 @@ impl PhysicalDevice {
|
|||||||
) -> Result<(), PhysicalDeviceError> {
|
) -> Result<(), PhysicalDeviceError> {
|
||||||
if !self.instance.enabled_extensions().qnx_screen_surface {
|
if !self.instance.enabled_extensions().qnx_screen_surface {
|
||||||
return Err(PhysicalDeviceError::RequirementNotMet {
|
return Err(PhysicalDeviceError::RequirementNotMet {
|
||||||
required_for: "`qnx_screen_presentation_support`",
|
required_for: "`PhysicalDevice::qnx_screen_presentation_support`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
instance_extensions: &["qnx_screen_surface"],
|
instance_extensions: &["qnx_screen_surface"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -1486,7 +1490,7 @@ impl PhysicalDevice {
|
|||||||
|| self.instance.enabled_extensions().khr_surface)
|
|| self.instance.enabled_extensions().khr_surface)
|
||||||
{
|
{
|
||||||
return Err(PhysicalDeviceError::RequirementNotMet {
|
return Err(PhysicalDeviceError::RequirementNotMet {
|
||||||
required_for: "`surface_capabilities`",
|
required_for: "`PhysicalDevice::surface_capabilities`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
instance_extensions: &["khr_get_surface_capabilities2", "khr_surface"],
|
instance_extensions: &["khr_get_surface_capabilities2", "khr_surface"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -1655,10 +1659,10 @@ impl PhysicalDevice {
|
|||||||
.supported_transforms
|
.supported_transforms
|
||||||
.into(),
|
.into(),
|
||||||
|
|
||||||
current_transform: SupportedSurfaceTransforms::from(
|
current_transform: SurfaceTransforms::from(
|
||||||
capabilities_vk.surface_capabilities.current_transform,
|
capabilities_vk.surface_capabilities.current_transform,
|
||||||
)
|
)
|
||||||
.iter()
|
.into_iter()
|
||||||
.next()
|
.next()
|
||||||
.unwrap(), // TODO:
|
.unwrap(), // TODO:
|
||||||
supported_composite_alpha: capabilities_vk
|
supported_composite_alpha: capabilities_vk
|
||||||
@ -1668,7 +1672,7 @@ impl PhysicalDevice {
|
|||||||
supported_usage_flags: {
|
supported_usage_flags: {
|
||||||
let usage =
|
let usage =
|
||||||
ImageUsage::from(capabilities_vk.surface_capabilities.supported_usage_flags);
|
ImageUsage::from(capabilities_vk.surface_capabilities.supported_usage_flags);
|
||||||
debug_assert!(usage.color_attachment); // specs say that this must be true
|
debug_assert!(usage.intersects(ImageUsage::COLOR_ATTACHMENT)); // specs say that this must be true
|
||||||
usage
|
usage
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1711,7 +1715,7 @@ impl PhysicalDevice {
|
|||||||
|| self.instance.enabled_extensions().khr_surface)
|
|| self.instance.enabled_extensions().khr_surface)
|
||||||
{
|
{
|
||||||
return Err(PhysicalDeviceError::RequirementNotMet {
|
return Err(PhysicalDeviceError::RequirementNotMet {
|
||||||
required_for: "`surface_formats`",
|
required_for: "`PhysicalDevice::surface_formats`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
instance_extensions: &["khr_get_surface_capabilities2", "khr_surface"],
|
instance_extensions: &["khr_get_surface_capabilities2", "khr_surface"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -1928,7 +1932,7 @@ impl PhysicalDevice {
|
|||||||
fn validate_surface_present_modes(&self, surface: &Surface) -> Result<(), PhysicalDeviceError> {
|
fn validate_surface_present_modes(&self, surface: &Surface) -> Result<(), PhysicalDeviceError> {
|
||||||
if !self.instance.enabled_extensions().khr_surface {
|
if !self.instance.enabled_extensions().khr_surface {
|
||||||
return Err(PhysicalDeviceError::RequirementNotMet {
|
return Err(PhysicalDeviceError::RequirementNotMet {
|
||||||
required_for: "`surface_present_modes`",
|
required_for: "`PhysicalDevice::surface_present_modes`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
instance_extensions: &["khr_surface"],
|
instance_extensions: &["khr_surface"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -2022,7 +2026,7 @@ impl PhysicalDevice {
|
|||||||
) -> Result<(), PhysicalDeviceError> {
|
) -> Result<(), PhysicalDeviceError> {
|
||||||
if !self.instance.enabled_extensions().khr_surface {
|
if !self.instance.enabled_extensions().khr_surface {
|
||||||
return Err(PhysicalDeviceError::RequirementNotMet {
|
return Err(PhysicalDeviceError::RequirementNotMet {
|
||||||
required_for: "`surface_support`",
|
required_for: "`PhysicalDevice::surface_support`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
instance_extensions: &["khr_surface"],
|
instance_extensions: &["khr_surface"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -2084,7 +2088,7 @@ impl PhysicalDevice {
|
|||||||
fn validate_tool_properties(&self) -> Result<(), PhysicalDeviceError> {
|
fn validate_tool_properties(&self) -> Result<(), PhysicalDeviceError> {
|
||||||
if !(self.api_version() >= Version::V1_3 || self.supported_extensions().ext_tooling_info) {
|
if !(self.api_version() >= Version::V1_3 || self.supported_extensions().ext_tooling_info) {
|
||||||
return Err(PhysicalDeviceError::RequirementNotMet {
|
return Err(PhysicalDeviceError::RequirementNotMet {
|
||||||
required_for: "`tooling_properties`",
|
required_for: "`PhysicalDevice::tooling_properties`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
api_version: Some(Version::V1_3),
|
api_version: Some(Version::V1_3),
|
||||||
device_extensions: &["ext_tooling_info"],
|
device_extensions: &["ext_tooling_info"],
|
||||||
@ -2195,7 +2199,7 @@ impl PhysicalDevice {
|
|||||||
) -> Result<(), PhysicalDeviceError> {
|
) -> Result<(), PhysicalDeviceError> {
|
||||||
if !self.instance.enabled_extensions().khr_wayland_surface {
|
if !self.instance.enabled_extensions().khr_wayland_surface {
|
||||||
return Err(PhysicalDeviceError::RequirementNotMet {
|
return Err(PhysicalDeviceError::RequirementNotMet {
|
||||||
required_for: "`wayland_presentation_support`",
|
required_for: "`PhysicalDevice::wayland_presentation_support`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
instance_extensions: &["khr_wayland_surface"],
|
instance_extensions: &["khr_wayland_surface"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -2250,7 +2254,7 @@ impl PhysicalDevice {
|
|||||||
) -> Result<(), PhysicalDeviceError> {
|
) -> Result<(), PhysicalDeviceError> {
|
||||||
if !self.instance.enabled_extensions().khr_win32_surface {
|
if !self.instance.enabled_extensions().khr_win32_surface {
|
||||||
return Err(PhysicalDeviceError::RequirementNotMet {
|
return Err(PhysicalDeviceError::RequirementNotMet {
|
||||||
required_for: "`win32_presentation_support`",
|
required_for: "`PhysicalDevice::win32_presentation_support`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
instance_extensions: &["khr_win32_surface"],
|
instance_extensions: &["khr_win32_surface"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -2304,7 +2308,7 @@ impl PhysicalDevice {
|
|||||||
) -> Result<(), PhysicalDeviceError> {
|
) -> Result<(), PhysicalDeviceError> {
|
||||||
if !self.instance.enabled_extensions().khr_xcb_surface {
|
if !self.instance.enabled_extensions().khr_xcb_surface {
|
||||||
return Err(PhysicalDeviceError::RequirementNotMet {
|
return Err(PhysicalDeviceError::RequirementNotMet {
|
||||||
required_for: "`xcb_presentation_support`",
|
required_for: "`PhysicalDevice::xcb_presentation_support`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
instance_extensions: &["khr_xcb_surface"],
|
instance_extensions: &["khr_xcb_surface"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -2368,7 +2372,7 @@ impl PhysicalDevice {
|
|||||||
) -> Result<(), PhysicalDeviceError> {
|
) -> Result<(), PhysicalDeviceError> {
|
||||||
if !self.instance.enabled_extensions().khr_xlib_surface {
|
if !self.instance.enabled_extensions().khr_xlib_surface {
|
||||||
return Err(PhysicalDeviceError::RequirementNotMet {
|
return Err(PhysicalDeviceError::RequirementNotMet {
|
||||||
required_for: "`xlib_presentation_support`",
|
required_for: "`PhysicalDevice::xlib_presentation_support`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
instance_extensions: &["khr_xlib_surface"],
|
instance_extensions: &["khr_xlib_surface"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -2420,8 +2424,9 @@ unsafe impl VulkanObject for PhysicalDevice {
|
|||||||
crate::impl_id_counter!(PhysicalDevice);
|
crate::impl_id_counter!(PhysicalDevice);
|
||||||
|
|
||||||
vulkan_enum! {
|
vulkan_enum! {
|
||||||
/// Type of a physical device.
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
|
|
||||||
|
/// Type of a physical device.
|
||||||
PhysicalDeviceType = PhysicalDeviceType(i32);
|
PhysicalDeviceType = PhysicalDeviceType(i32);
|
||||||
|
|
||||||
/// The device is an integrated GPU.
|
/// The device is an integrated GPU.
|
||||||
@ -2482,8 +2487,9 @@ impl Display for ConformanceVersion {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vulkan_enum! {
|
vulkan_enum! {
|
||||||
/// An identifier for the driver of a physical device.
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
|
|
||||||
|
/// An identifier for the driver of a physical device.
|
||||||
DriverId = DriverId(i32);
|
DriverId = DriverId(i32);
|
||||||
|
|
||||||
// TODO: document
|
// TODO: document
|
||||||
@ -2550,78 +2556,81 @@ pub struct ToolProperties {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vulkan_bitflags! {
|
vulkan_bitflags! {
|
||||||
/// The purpose of an active tool.
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
|
|
||||||
|
/// The purpose of an active tool.
|
||||||
ToolPurposes = ToolPurposeFlags(u32);
|
ToolPurposes = ToolPurposeFlags(u32);
|
||||||
|
|
||||||
/// The tool provides validation of API usage.
|
/// The tool provides validation of API usage.
|
||||||
validation = VALIDATION,
|
VALIDATION = VALIDATION,
|
||||||
|
|
||||||
/// The tool provides profiling of API usage.
|
/// The tool provides profiling of API usage.
|
||||||
profiling = PROFILING,
|
PROFILING = PROFILING,
|
||||||
|
|
||||||
/// The tool is capturing data about the application's API usage.
|
/// The tool is capturing data about the application's API usage.
|
||||||
tracing = TRACING,
|
TRACING = TRACING,
|
||||||
|
|
||||||
/// The tool provides additional API features or extensions on top of the underlying
|
/// The tool provides additional API features or extensions on top of the underlying
|
||||||
/// implementation.
|
/// implementation.
|
||||||
additional_features = ADDITIONAL_FEATURES,
|
ADDITIONAL_FEATURES = ADDITIONAL_FEATURES,
|
||||||
|
|
||||||
/// The tool modifies the API features, limits or extensions presented to the application.
|
/// The tool modifies the API features, limits or extensions presented to the application.
|
||||||
modifying_features = MODIFYING_FEATURES,
|
MODIFYING_FEATURES = MODIFYING_FEATURES,
|
||||||
|
|
||||||
/// The tool reports information to the user via a
|
/// The tool reports information to the user via a
|
||||||
/// [`DebugUtilsMessenger`](crate::instance::debug::DebugUtilsMessenger).
|
/// [`DebugUtilsMessenger`](crate::instance::debug::DebugUtilsMessenger).
|
||||||
debug_reporting = DEBUG_REPORTING_EXT {
|
DEBUG_REPORTING = DEBUG_REPORTING_EXT {
|
||||||
instance_extensions: [ext_debug_utils, ext_debug_report],
|
instance_extensions: [ext_debug_utils, ext_debug_report],
|
||||||
},
|
},
|
||||||
|
|
||||||
/// The tool consumes debug markers or object debug annotation, queue labels or command buffer
|
/// The tool consumes debug markers or object debug annotation, queue labels or command buffer
|
||||||
/// labels.
|
/// labels.
|
||||||
debug_markers = DEBUG_MARKERS_EXT {
|
DEBUG_MARKERS = DEBUG_MARKERS_EXT {
|
||||||
device_extensions: [ext_debug_marker],
|
device_extensions: [ext_debug_marker],
|
||||||
instance_extensions: [ext_debug_utils],
|
instance_extensions: [ext_debug_utils],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
vulkan_bitflags! {
|
vulkan_bitflags! {
|
||||||
/// Specifies which subgroup operations are supported.
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
|
|
||||||
|
/// Specifies which subgroup operations are supported.
|
||||||
SubgroupFeatures = SubgroupFeatureFlags(u32);
|
SubgroupFeatures = SubgroupFeatureFlags(u32);
|
||||||
|
|
||||||
// TODO: document
|
// TODO: document
|
||||||
basic = BASIC,
|
BASIC = BASIC,
|
||||||
|
|
||||||
// TODO: document
|
// TODO: document
|
||||||
vote = VOTE,
|
VOTE = VOTE,
|
||||||
|
|
||||||
// TODO: document
|
// TODO: document
|
||||||
arithmetic = ARITHMETIC,
|
ARITHMETIC = ARITHMETIC,
|
||||||
|
|
||||||
// TODO: document
|
// TODO: document
|
||||||
ballot = BALLOT,
|
BALLOT = BALLOT,
|
||||||
|
|
||||||
// TODO: document
|
// TODO: document
|
||||||
shuffle = SHUFFLE,
|
SHUFFLE = SHUFFLE,
|
||||||
|
|
||||||
// TODO: document
|
// TODO: document
|
||||||
shuffle_relative = SHUFFLE_RELATIVE,
|
SHUFFLE_RELATIVE = SHUFFLE_RELATIVE,
|
||||||
|
|
||||||
// TODO: document
|
// TODO: document
|
||||||
clustered = CLUSTERED,
|
CLUSTERED = CLUSTERED,
|
||||||
|
|
||||||
// TODO: document
|
// TODO: document
|
||||||
quad = QUAD,
|
QUAD = QUAD,
|
||||||
|
|
||||||
// TODO: document
|
// TODO: document
|
||||||
partitioned = PARTITIONED_NV {
|
PARTITIONED = PARTITIONED_NV {
|
||||||
device_extensions: [nv_shader_subgroup_partitioned],
|
device_extensions: [nv_shader_subgroup_partitioned],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
vulkan_enum! {
|
vulkan_enum! {
|
||||||
/// Specifies how the device clips single point primitives.
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
|
|
||||||
|
/// Specifies how the device clips single point primitives.
|
||||||
PointClippingBehavior = PointClippingBehavior(i32);
|
PointClippingBehavior = PointClippingBehavior(i32);
|
||||||
|
|
||||||
/// Points are clipped if they lie outside any clip plane, both those bounding the view volume
|
/// Points are clipped if they lie outside any clip plane, both those bounding the view volume
|
||||||
@ -2633,8 +2642,9 @@ vulkan_enum! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vulkan_enum! {
|
vulkan_enum! {
|
||||||
/// Specifies whether, and how, shader float controls can be set independently.
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
|
|
||||||
|
/// Specifies whether, and how, shader float controls can be set independently.
|
||||||
ShaderFloatControlsIndependence = ShaderFloatControlsIndependence(i32);
|
ShaderFloatControlsIndependence = ShaderFloatControlsIndependence(i32);
|
||||||
|
|
||||||
// TODO: document
|
// TODO: document
|
||||||
|
@ -1126,7 +1126,7 @@ impl<'a> QueueGuard<'a> {
|
|||||||
.ext_debug_utils
|
.ext_debug_utils
|
||||||
{
|
{
|
||||||
return Err(QueueError::RequirementNotMet {
|
return Err(QueueError::RequirementNotMet {
|
||||||
required_for: "`begin_debug_utils_label`",
|
required_for: "`QueueGuard::begin_debug_utils_label`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
instance_extensions: &["ext_debug_utils"],
|
instance_extensions: &["ext_debug_utils"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -1183,7 +1183,7 @@ impl<'a> QueueGuard<'a> {
|
|||||||
.ext_debug_utils
|
.ext_debug_utils
|
||||||
{
|
{
|
||||||
return Err(QueueError::RequirementNotMet {
|
return Err(QueueError::RequirementNotMet {
|
||||||
required_for: "`end_debug_utils_label`",
|
required_for: "`QueueGuard::end_debug_utils_label`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
instance_extensions: &["ext_debug_utils"],
|
instance_extensions: &["ext_debug_utils"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -1233,7 +1233,7 @@ impl<'a> QueueGuard<'a> {
|
|||||||
.ext_debug_utils
|
.ext_debug_utils
|
||||||
{
|
{
|
||||||
return Err(QueueError::RequirementNotMet {
|
return Err(QueueError::RequirementNotMet {
|
||||||
required_for: "`insert_debug_utils_label`",
|
required_for: "`QueueGuard::insert_debug_utils_label`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
instance_extensions: &["ext_debug_utils"],
|
instance_extensions: &["ext_debug_utils"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -1592,7 +1592,7 @@ impl QueueFamilyProperties {
|
|||||||
/// Returns whether the queues of this family support a particular pipeline stage.
|
/// Returns whether the queues of this family support a particular pipeline stage.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn supports_stage(&self, stage: PipelineStage) -> bool {
|
pub fn supports_stage(&self, stage: PipelineStage) -> bool {
|
||||||
ash::vk::QueueFlags::from(self.queue_flags).contains(stage.required_queue_flags())
|
self.queue_flags.contains(stage.required_queue_flags())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1614,34 +1614,35 @@ impl From<ash::vk::QueueFamilyProperties> for QueueFamilyProperties {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vulkan_bitflags! {
|
vulkan_bitflags! {
|
||||||
/// Attributes of a queue or queue family.
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
|
|
||||||
|
/// Attributes of a queue or queue family.
|
||||||
QueueFlags = QueueFlags(u32);
|
QueueFlags = QueueFlags(u32);
|
||||||
|
|
||||||
/// Queues of this family can execute graphics operations.
|
/// Queues of this family can execute graphics operations.
|
||||||
graphics = GRAPHICS,
|
GRAPHICS = GRAPHICS,
|
||||||
|
|
||||||
/// Queues of this family can execute compute operations.
|
/// Queues of this family can execute compute operations.
|
||||||
compute = COMPUTE,
|
COMPUTE = COMPUTE,
|
||||||
|
|
||||||
/// Queues of this family can execute transfer operations.
|
/// Queues of this family can execute transfer operations.
|
||||||
transfer = TRANSFER,
|
TRANSFER = TRANSFER,
|
||||||
|
|
||||||
/// Queues of this family can execute sparse memory management operations.
|
/// Queues of this family can execute sparse memory management operations.
|
||||||
sparse_binding = SPARSE_BINDING,
|
SPARSE_BINDING = SPARSE_BINDING,
|
||||||
|
|
||||||
/// Queues of this family can be created using the `protected` flag.
|
/// Queues of this family can be created using the `protected` flag.
|
||||||
protected = PROTECTED {
|
PROTECTED = PROTECTED {
|
||||||
api_version: V1_1,
|
api_version: V1_1,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Queues of this family can execute video decode operations.
|
/// Queues of this family can execute video decode operations.
|
||||||
video_decode = VIDEO_DECODE_KHR {
|
VIDEO_DECODE = VIDEO_DECODE_KHR {
|
||||||
device_extensions: [khr_video_decode_queue],
|
device_extensions: [khr_video_decode_queue],
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Queues of this family can execute video encode operations.
|
/// Queues of this family can execute video encode operations.
|
||||||
video_encode = VIDEO_ENCODE_KHR {
|
VIDEO_ENCODE = VIDEO_ENCODE_KHR {
|
||||||
device_extensions: [khr_video_encode_queue],
|
device_extensions: [khr_video_encode_queue],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -107,8 +107,8 @@ impl Format {
|
|||||||
note = "Use PhysicalDevice::format_properties instead"
|
note = "Use PhysicalDevice::format_properties instead"
|
||||||
)]
|
)]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn properties(&self, physical_device: PhysicalDevice) -> FormatProperties {
|
pub fn properties(self, physical_device: PhysicalDevice) -> FormatProperties {
|
||||||
physical_device.format_properties(*self).unwrap()
|
physical_device.format_properties(self).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns whether the format can be used with a storage image, without specifying
|
/// Returns whether the format can be used with a storage image, without specifying
|
||||||
@ -118,9 +118,9 @@ impl Format {
|
|||||||
/// [`shader_storage_image_write_without_format`](crate::device::Features::shader_storage_image_write_without_format)
|
/// [`shader_storage_image_write_without_format`](crate::device::Features::shader_storage_image_write_without_format)
|
||||||
/// features are enabled on the device.
|
/// features are enabled on the device.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn shader_storage_image_without_format(&self) -> bool {
|
pub fn shader_storage_image_without_format(self) -> bool {
|
||||||
matches!(
|
matches!(
|
||||||
*self,
|
self,
|
||||||
Format::R8G8B8A8_UNORM
|
Format::R8G8B8A8_UNORM
|
||||||
| Format::R8G8B8A8_SNORM
|
| Format::R8G8B8A8_SNORM
|
||||||
| Format::R8G8B8A8_UINT
|
| Format::R8G8B8A8_UINT
|
||||||
@ -254,7 +254,7 @@ pub enum ChromaSampling {
|
|||||||
|
|
||||||
impl ChromaSampling {
|
impl ChromaSampling {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn subsampled_extent(&self, mut extent: [u32; 3]) -> [u32; 3] {
|
pub fn subsampled_extent(self, mut extent: [u32; 3]) -> [u32; 3] {
|
||||||
match self {
|
match self {
|
||||||
ChromaSampling::Mode444 => (),
|
ChromaSampling::Mode444 => (),
|
||||||
ChromaSampling::Mode422 => {
|
ChromaSampling::Mode422 => {
|
||||||
@ -743,138 +743,139 @@ impl FormatProperties {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vulkan_bitflags! {
|
vulkan_bitflags! {
|
||||||
/// The features supported by a device for an image or buffer with a particular format.
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
|
|
||||||
|
/// The features supported by a device for an image or buffer with a particular format.
|
||||||
FormatFeatures = FormatFeatureFlags2(u64);
|
FormatFeatures = FormatFeatureFlags2(u64);
|
||||||
|
|
||||||
/* Image usage */
|
/* Image usage */
|
||||||
|
|
||||||
/// Can be used with a sampled image descriptor.
|
/// Can be used with a sampled image descriptor.
|
||||||
sampled_image = SAMPLED_IMAGE,
|
SAMPLED_IMAGE = SAMPLED_IMAGE,
|
||||||
|
|
||||||
/// Can be used with a storage image descriptor.
|
/// Can be used with a storage image descriptor.
|
||||||
storage_image = STORAGE_IMAGE,
|
STORAGE_IMAGE = STORAGE_IMAGE,
|
||||||
|
|
||||||
/// Can be used with a storage image descriptor with atomic operations in a shader.
|
/// Can be used with a storage image descriptor with atomic operations in a shader.
|
||||||
storage_image_atomic = STORAGE_IMAGE_ATOMIC,
|
STORAGE_IMAGE_ATOMIC = STORAGE_IMAGE_ATOMIC,
|
||||||
|
|
||||||
/// Can be used with a storage image descriptor for reading, without specifying a format on the
|
/// Can be used with a storage image descriptor for reading, without specifying a format on the
|
||||||
/// image view.
|
/// image view.
|
||||||
storage_read_without_format = STORAGE_READ_WITHOUT_FORMAT {
|
STORAGE_READ_WITHOUT_FORMAT = STORAGE_READ_WITHOUT_FORMAT {
|
||||||
api_version: V1_3,
|
api_version: V1_3,
|
||||||
device_extensions: [khr_format_feature_flags2],
|
device_extensions: [khr_format_feature_flags2],
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Can be used with a storage image descriptor for writing, without specifying a format on the
|
/// Can be used with a storage image descriptor for writing, without specifying a format on the
|
||||||
/// image view.
|
/// image view.
|
||||||
storage_write_without_format = STORAGE_WRITE_WITHOUT_FORMAT {
|
STORAGE_WRITE_WITHOUT_FORMAT = STORAGE_WRITE_WITHOUT_FORMAT {
|
||||||
api_version: V1_3,
|
api_version: V1_3,
|
||||||
device_extensions: [khr_format_feature_flags2],
|
device_extensions: [khr_format_feature_flags2],
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Can be used with a color attachment in a framebuffer, or with an input attachment
|
/// Can be used with a color attachment in a framebuffer, or with an input attachment
|
||||||
/// descriptor.
|
/// descriptor.
|
||||||
color_attachment = COLOR_ATTACHMENT,
|
COLOR_ATTACHMENT = COLOR_ATTACHMENT,
|
||||||
|
|
||||||
/// Can be used with a color attachment in a framebuffer with blending, or with an input
|
/// Can be used with a color attachment in a framebuffer with blending, or with an input
|
||||||
/// attachment descriptor.
|
/// attachment descriptor.
|
||||||
color_attachment_blend = COLOR_ATTACHMENT_BLEND,
|
COLOR_ATTACHMENT_BLEND = COLOR_ATTACHMENT_BLEND,
|
||||||
|
|
||||||
/// Can be used with a depth/stencil attachment in a framebuffer, or with an input attachment
|
/// Can be used with a depth/stencil attachment in a framebuffer, or with an input attachment
|
||||||
/// descriptor.
|
/// descriptor.
|
||||||
depth_stencil_attachment = DEPTH_STENCIL_ATTACHMENT,
|
DEPTH_STENCIL_ATTACHMENT = DEPTH_STENCIL_ATTACHMENT,
|
||||||
|
|
||||||
/// Can be used with a fragment density map attachment in a framebuffer.
|
/// Can be used with a fragment density map attachment in a framebuffer.
|
||||||
fragment_density_map = FRAGMENT_DENSITY_MAP_EXT {
|
FRAGMENT_DENSITY_MAP = FRAGMENT_DENSITY_MAP_EXT {
|
||||||
device_extensions: [ext_fragment_density_map],
|
device_extensions: [ext_fragment_density_map],
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Can be used with a fragment shading rate attachment in a framebuffer.
|
/// Can be used with a fragment shading rate attachment in a framebuffer.
|
||||||
fragment_shading_rate_attachment = FRAGMENT_SHADING_RATE_ATTACHMENT_KHR {
|
FRAGMENT_SHADING_RATE_ATTACHMENT = FRAGMENT_SHADING_RATE_ATTACHMENT_KHR {
|
||||||
device_extensions: [khr_fragment_shading_rate],
|
device_extensions: [khr_fragment_shading_rate],
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Can be used with the source image in a transfer (copy) operation.
|
/// Can be used with the source image in a transfer (copy) operation.
|
||||||
transfer_src = TRANSFER_SRC {
|
TRANSFER_SRC = TRANSFER_SRC {
|
||||||
api_version: V1_1,
|
api_version: V1_1,
|
||||||
device_extensions: [khr_maintenance1],
|
device_extensions: [khr_maintenance1],
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Can be used with the destination image in a transfer (copy) operation.
|
/// Can be used with the destination image in a transfer (copy) operation.
|
||||||
transfer_dst = TRANSFER_DST {
|
TRANSFER_DST = TRANSFER_DST {
|
||||||
api_version: V1_1,
|
api_version: V1_1,
|
||||||
device_extensions: [khr_maintenance1],
|
device_extensions: [khr_maintenance1],
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Can be used with the source image in a blit operation.
|
/// Can be used with the source image in a blit operation.
|
||||||
blit_src = BLIT_SRC,
|
BLIT_SRC = BLIT_SRC,
|
||||||
|
|
||||||
/// Can be used with the destination image in a blit operation.
|
/// Can be used with the destination image in a blit operation.
|
||||||
blit_dst = BLIT_DST,
|
BLIT_DST = BLIT_DST,
|
||||||
|
|
||||||
/* Sampling */
|
/* Sampling */
|
||||||
|
|
||||||
/// Can be used with samplers or as a blit source, using the
|
/// Can be used with samplers or as a blit source, using the
|
||||||
/// [`Linear`](crate::sampler::Filter::Linear) filter.
|
/// [`Linear`](crate::sampler::Filter::Linear) filter.
|
||||||
sampled_image_filter_linear = SAMPLED_IMAGE_FILTER_LINEAR,
|
SAMPLED_IMAGE_FILTER_LINEAR = SAMPLED_IMAGE_FILTER_LINEAR,
|
||||||
|
|
||||||
/// Can be used with samplers or as a blit source, using the
|
/// Can be used with samplers or as a blit source, using the
|
||||||
/// [`Cubic`](crate::sampler::Filter::Cubic) filter.
|
/// [`Cubic`](crate::sampler::Filter::Cubic) filter.
|
||||||
sampled_image_filter_cubic = SAMPLED_IMAGE_FILTER_CUBIC_EXT {
|
SAMPLED_IMAGE_FILTER_CUBIC = SAMPLED_IMAGE_FILTER_CUBIC_EXT {
|
||||||
device_extensions: [ext_filter_cubic, img_filter_cubic],
|
device_extensions: [ext_filter_cubic, img_filter_cubic],
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Can be used with samplers using a reduction mode of
|
/// Can be used with samplers using a reduction mode of
|
||||||
/// [`Min`](crate::sampler::SamplerReductionMode::Min) or
|
/// [`Min`](crate::sampler::SamplerReductionMode::Min) or
|
||||||
/// [`Max`](crate::sampler::SamplerReductionMode::Max).
|
/// [`Max`](crate::sampler::SamplerReductionMode::Max).
|
||||||
sampled_image_filter_minmax = SAMPLED_IMAGE_FILTER_MINMAX {
|
SAMPLED_IMAGE_FILTER_MINMAX = SAMPLED_IMAGE_FILTER_MINMAX {
|
||||||
api_version: V1_2,
|
api_version: V1_2,
|
||||||
device_extensions: [ext_sampler_filter_minmax],
|
device_extensions: [ext_sampler_filter_minmax],
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Can be used with sampler YCbCr conversions using a chroma offset of
|
/// Can be used with sampler YCbCr conversions using a chroma offset of
|
||||||
/// [`Midpoint`](crate::sampler::ycbcr::ChromaLocation::Midpoint).
|
/// [`Midpoint`](crate::sampler::ycbcr::ChromaLocation::Midpoint).
|
||||||
midpoint_chroma_samples = MIDPOINT_CHROMA_SAMPLES {
|
MIDPOINT_CHROMA_SAMPLES = MIDPOINT_CHROMA_SAMPLES {
|
||||||
api_version: V1_1,
|
api_version: V1_1,
|
||||||
device_extensions: [khr_sampler_ycbcr_conversion],
|
device_extensions: [khr_sampler_ycbcr_conversion],
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Can be used with sampler YCbCr conversions using a chroma offset of
|
/// Can be used with sampler YCbCr conversions using a chroma offset of
|
||||||
/// [`CositedEven`](crate::sampler::ycbcr::ChromaLocation::CositedEven).
|
/// [`CositedEven`](crate::sampler::ycbcr::ChromaLocation::CositedEven).
|
||||||
cosited_chroma_samples = COSITED_CHROMA_SAMPLES {
|
COSITED_CHROMA_SAMPLES = COSITED_CHROMA_SAMPLES {
|
||||||
api_version: V1_1,
|
api_version: V1_1,
|
||||||
device_extensions: [khr_sampler_ycbcr_conversion],
|
device_extensions: [khr_sampler_ycbcr_conversion],
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Can be used with sampler YCbCr conversions using the
|
/// Can be used with sampler YCbCr conversions using the
|
||||||
/// [`Linear`](crate::sampler::Filter::Linear) chroma filter.
|
/// [`Linear`](crate::sampler::Filter::Linear) chroma filter.
|
||||||
sampled_image_ycbcr_conversion_linear_filter = SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER {
|
SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER = SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER {
|
||||||
api_version: V1_1,
|
api_version: V1_1,
|
||||||
device_extensions: [khr_sampler_ycbcr_conversion],
|
device_extensions: [khr_sampler_ycbcr_conversion],
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Can be used with sampler YCbCr conversions whose chroma filter differs from the filters of
|
/// Can be used with sampler YCbCr conversions whose chroma filter differs from the filters of
|
||||||
/// the base sampler.
|
/// the base sampler.
|
||||||
sampled_image_ycbcr_conversion_separate_reconstruction_filter = SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER {
|
SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER = SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER {
|
||||||
api_version: V1_1,
|
api_version: V1_1,
|
||||||
device_extensions: [khr_sampler_ycbcr_conversion],
|
device_extensions: [khr_sampler_ycbcr_conversion],
|
||||||
},
|
},
|
||||||
|
|
||||||
/// When used with a sampler YCbCr conversion, the implementation will always perform
|
/// When used with a sampler YCbCr conversion, the implementation will always perform
|
||||||
/// explicit chroma reconstruction.
|
/// explicit chroma reconstruction.
|
||||||
sampled_image_ycbcr_conversion_chroma_reconstruction_explicit = SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT {
|
SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT = SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT {
|
||||||
api_version: V1_1,
|
api_version: V1_1,
|
||||||
device_extensions: [khr_sampler_ycbcr_conversion],
|
device_extensions: [khr_sampler_ycbcr_conversion],
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Can be used with sampler YCbCr conversions with forced explicit reconstruction.
|
/// Can be used with sampler YCbCr conversions with forced explicit reconstruction.
|
||||||
sampled_image_ycbcr_conversion_chroma_reconstruction_explicit_forceable = SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE {
|
SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE = SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE {
|
||||||
api_version: V1_1,
|
api_version: V1_1,
|
||||||
device_extensions: [khr_sampler_ycbcr_conversion],
|
device_extensions: [khr_sampler_ycbcr_conversion],
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Can be used with samplers using depth comparison.
|
/// Can be used with samplers using depth comparison.
|
||||||
sampled_image_depth_comparison = SAMPLED_IMAGE_DEPTH_COMPARISON {
|
SAMPLED_IMAGE_DEPTH_COMPARISON = SAMPLED_IMAGE_DEPTH_COMPARISON {
|
||||||
api_version: V1_3,
|
api_version: V1_3,
|
||||||
device_extensions: [khr_format_feature_flags2],
|
device_extensions: [khr_format_feature_flags2],
|
||||||
},
|
},
|
||||||
@ -882,29 +883,31 @@ vulkan_bitflags! {
|
|||||||
/* Video */
|
/* Video */
|
||||||
|
|
||||||
/// Can be used with the output image of a video decode operation.
|
/// Can be used with the output image of a video decode operation.
|
||||||
video_decode_output = VIDEO_DECODE_OUTPUT_KHR {
|
VIDEO_DECODE_OUTPUT = VIDEO_DECODE_OUTPUT_KHR {
|
||||||
device_extensions: [khr_video_decode_queue],
|
device_extensions: [khr_video_decode_queue],
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Can be used with the DPB image of a video decode operation.
|
/// Can be used with the DPB image of a video decode operation.
|
||||||
video_decode_dpb = VIDEO_DECODE_DPB_KHR {
|
VIDEO_DECODE_DPB = VIDEO_DECODE_DPB_KHR {
|
||||||
device_extensions: [khr_video_decode_queue],
|
device_extensions: [khr_video_decode_queue],
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Can be used with the input image of a video encode operation.
|
/// Can be used with the input image of a video encode operation.
|
||||||
video_encode_input = VIDEO_ENCODE_INPUT_KHR {
|
VIDEO_ENCODE_INPUT = VIDEO_ENCODE_INPUT_KHR {
|
||||||
device_extensions: [khr_video_encode_queue],
|
device_extensions: [khr_video_encode_queue],
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Can be used with the DPB image of a video encode operation.
|
/// Can be used with the DPB image of a video encode operation.
|
||||||
video_encode_dpb = VIDEO_ENCODE_DPB_KHR {
|
VIDEO_ENCODE_DPB = VIDEO_ENCODE_DPB_KHR {
|
||||||
device_extensions: [khr_video_encode_queue],
|
device_extensions: [khr_video_encode_queue],
|
||||||
},
|
},
|
||||||
|
|
||||||
/* Misc image features */
|
/* Misc image features */
|
||||||
|
|
||||||
/// For multi-planar formats, can be used with images created with the `disjoint` flag.
|
/// For multi-planar formats, can be used with images created with the [`DISJOINT`] flag.
|
||||||
disjoint = DISJOINT {
|
///
|
||||||
|
/// [`DISJOINT`]: crate::image::ImageCreateFlags::DISJOINT
|
||||||
|
DISJOINT = DISJOINT {
|
||||||
api_version: V1_1,
|
api_version: V1_1,
|
||||||
device_extensions: [khr_sampler_ycbcr_conversion],
|
device_extensions: [khr_sampler_ycbcr_conversion],
|
||||||
},
|
},
|
||||||
@ -912,20 +915,20 @@ vulkan_bitflags! {
|
|||||||
/* Buffer usage */
|
/* Buffer usage */
|
||||||
|
|
||||||
/// Can be used with a uniform texel buffer descriptor.
|
/// Can be used with a uniform texel buffer descriptor.
|
||||||
uniform_texel_buffer = UNIFORM_TEXEL_BUFFER,
|
UNIFORM_TEXEL_BUFFER = UNIFORM_TEXEL_BUFFER,
|
||||||
|
|
||||||
/// Can be used with a storage texel buffer descriptor.
|
/// Can be used with a storage texel buffer descriptor.
|
||||||
storage_texel_buffer = STORAGE_TEXEL_BUFFER,
|
STORAGE_TEXEL_BUFFER = STORAGE_TEXEL_BUFFER,
|
||||||
|
|
||||||
/// Can be used with a storage texel buffer descriptor with atomic operations in a shader.
|
/// Can be used with a storage texel buffer descriptor with atomic operations in a shader.
|
||||||
storage_texel_buffer_atomic = STORAGE_TEXEL_BUFFER_ATOMIC,
|
STORAGE_TEXEL_BUFFER_ATOMIC = STORAGE_TEXEL_BUFFER_ATOMIC,
|
||||||
|
|
||||||
/// Can be used as the format of a vertex attribute in the vertex input state of a graphics
|
/// Can be used as the format of a vertex attribute in the vertex input state of a graphics
|
||||||
/// pipeline.
|
/// pipeline.
|
||||||
vertex_buffer = VERTEX_BUFFER,
|
VERTEX_BUFFER = VERTEX_BUFFER,
|
||||||
|
|
||||||
/// Can be used with the vertex buffer of an acceleration structure.
|
/// Can be used with the vertex buffer of an acceleration structure.
|
||||||
acceleration_structure_vertex_buffer = ACCELERATION_STRUCTURE_VERTEX_BUFFER_KHR {
|
ACCELERATION_STRUCTURE_VERTEX_BUFFER = ACCELERATION_STRUCTURE_VERTEX_BUFFER_KHR {
|
||||||
device_extensions: [khr_acceleration_structure],
|
device_extensions: [khr_acceleration_structure],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -7,187 +7,90 @@
|
|||||||
// notice may not be copied, modified, or distributed except
|
// notice may not be copied, modified, or distributed except
|
||||||
// according to those terms.
|
// according to those terms.
|
||||||
|
|
||||||
use crate::macros::{vulkan_bitflags, vulkan_enum};
|
use crate::macros::vulkan_bitflags_enum;
|
||||||
|
|
||||||
|
vulkan_bitflags_enum! {
|
||||||
|
#[non_exhaustive]
|
||||||
|
|
||||||
|
/// A set of [`ImageAspect`] values.
|
||||||
|
ImageAspects,
|
||||||
|
|
||||||
vulkan_enum! {
|
|
||||||
/// An individual data type within an image.
|
/// An individual data type within an image.
|
||||||
///
|
///
|
||||||
/// Most images have only the `Color` aspect, but some may have several.
|
/// Most images have only the [`Color`] aspect, but some may have others.
|
||||||
#[non_exhaustive]
|
///
|
||||||
ImageAspect = ImageAspectFlags(u32);
|
/// [`Color`]: ImageAspect::Color
|
||||||
|
ImageAspect,
|
||||||
|
|
||||||
// TODO: document
|
= ImageAspectFlags(u32);
|
||||||
Color = COLOR,
|
|
||||||
|
|
||||||
// TODO: document
|
/// The single aspect of images with a color [format], or the combined aspect of all planes of
|
||||||
Depth = DEPTH,
|
/// images with a multi-planar format.
|
||||||
|
///
|
||||||
|
/// [format]: crate::format::Format
|
||||||
|
COLOR, Color = COLOR,
|
||||||
|
|
||||||
// TODO: document
|
/// The single aspect of images with a depth [format], or one of the two aspects of images
|
||||||
Stencil = STENCIL,
|
/// with a combined depth/stencil format.
|
||||||
|
///
|
||||||
|
/// [format]: crate::format::Format
|
||||||
|
DEPTH, Depth = DEPTH,
|
||||||
|
|
||||||
// TODO: document
|
/// The single aspect of images with a stencil [format], or one of the two aspects of images
|
||||||
Metadata = METADATA,
|
/// with a combined depth/stencil format.
|
||||||
|
///
|
||||||
|
/// [format]: crate::format::Format
|
||||||
|
STENCIL, Stencil = STENCIL,
|
||||||
|
|
||||||
// TODO: document
|
/// An aspect used with sparse memory on some implementations, to hold implementation-defined
|
||||||
Plane0 = PLANE_0 {
|
/// metadata of an image.
|
||||||
|
METADATA, Metadata = METADATA,
|
||||||
|
|
||||||
|
/// The first plane of an image with a multi-planar [format], holding the green color component.
|
||||||
|
///
|
||||||
|
/// [format]: crate::format::Format
|
||||||
|
PLANE_0, Plane0 = PLANE_0 {
|
||||||
api_version: V1_1,
|
api_version: V1_1,
|
||||||
device_extensions: [khr_sampler_ycbcr_conversion],
|
device_extensions: [khr_sampler_ycbcr_conversion],
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: document
|
/// The second plane of an image with a multi-planar [format], holding the blue color component
|
||||||
Plane1 = PLANE_1 {
|
/// if the format has three planes, and a combination of blue and red if the format has two
|
||||||
|
/// planes.
|
||||||
|
///
|
||||||
|
/// [format]: crate::format::Format
|
||||||
|
PLANE_1, Plane1 = PLANE_1 {
|
||||||
api_version: V1_1,
|
api_version: V1_1,
|
||||||
device_extensions: [khr_sampler_ycbcr_conversion],
|
device_extensions: [khr_sampler_ycbcr_conversion],
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: document
|
/// The third plane of an image with a multi-planar [format], holding the red color component.
|
||||||
Plane2 = PLANE_2 {
|
PLANE_2, Plane2 = PLANE_2 {
|
||||||
api_version: V1_1,
|
api_version: V1_1,
|
||||||
device_extensions: [khr_sampler_ycbcr_conversion],
|
device_extensions: [khr_sampler_ycbcr_conversion],
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: document
|
/// The first memory plane of images created through the [`ext_image_drm_format_modifier`]
|
||||||
MemoryPlane0 = MEMORY_PLANE_0_EXT {
|
/// extension.
|
||||||
|
///
|
||||||
|
/// [`ext_image_drm_format_modifier`]: crate::device::DeviceExtensions::ext_image_drm_format_modifier
|
||||||
|
MEMORY_PLANE_0, MemoryPlane0 = MEMORY_PLANE_0_EXT {
|
||||||
device_extensions: [ext_image_drm_format_modifier],
|
device_extensions: [ext_image_drm_format_modifier],
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: document
|
/// The second memory plane of images created through the [`ext_image_drm_format_modifier`]
|
||||||
MemoryPlane1 = MEMORY_PLANE_1_EXT {
|
/// extension.
|
||||||
|
///
|
||||||
|
/// [`ext_image_drm_format_modifier`]: crate::device::DeviceExtensions::ext_image_drm_format_modifier
|
||||||
|
MEMORY_PLANE_1, MemoryPlane1 = MEMORY_PLANE_1_EXT {
|
||||||
device_extensions: [ext_image_drm_format_modifier],
|
device_extensions: [ext_image_drm_format_modifier],
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: document
|
/// The third memory plane of images created through the [`ext_image_drm_format_modifier`]
|
||||||
MemoryPlane2 = MEMORY_PLANE_2_EXT {
|
/// extension.
|
||||||
|
///
|
||||||
|
/// [`ext_image_drm_format_modifier`]: crate::device::DeviceExtensions::ext_image_drm_format_modifier
|
||||||
|
MEMORY_PLANE_2, MemoryPlane2 = MEMORY_PLANE_2_EXT {
|
||||||
device_extensions: [ext_image_drm_format_modifier],
|
device_extensions: [ext_image_drm_format_modifier],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
vulkan_bitflags! {
|
|
||||||
/// A mask specifying one or more `ImageAspect`s.
|
|
||||||
#[non_exhaustive]
|
|
||||||
ImageAspects = ImageAspectFlags(u32);
|
|
||||||
|
|
||||||
// TODO: document
|
|
||||||
color = COLOR,
|
|
||||||
|
|
||||||
// TODO: document
|
|
||||||
depth = DEPTH,
|
|
||||||
|
|
||||||
// TODO: document
|
|
||||||
stencil = STENCIL,
|
|
||||||
|
|
||||||
// TODO: document
|
|
||||||
metadata = METADATA,
|
|
||||||
|
|
||||||
// TODO: document
|
|
||||||
plane0 = PLANE_0 {
|
|
||||||
api_version: V1_1,
|
|
||||||
device_extensions: [khr_sampler_ycbcr_conversion],
|
|
||||||
},
|
|
||||||
|
|
||||||
// TODO: document
|
|
||||||
plane1 = PLANE_1 {
|
|
||||||
api_version: V1_1,
|
|
||||||
device_extensions: [khr_sampler_ycbcr_conversion],
|
|
||||||
},
|
|
||||||
|
|
||||||
// TODO: document
|
|
||||||
plane2 = PLANE_2 {
|
|
||||||
api_version: V1_1,
|
|
||||||
device_extensions: [khr_sampler_ycbcr_conversion],
|
|
||||||
},
|
|
||||||
|
|
||||||
// TODO: document
|
|
||||||
memory_plane0 = MEMORY_PLANE_0_EXT {
|
|
||||||
device_extensions: [ext_image_drm_format_modifier],
|
|
||||||
},
|
|
||||||
|
|
||||||
// TODO: document
|
|
||||||
memory_plane1 = MEMORY_PLANE_1_EXT {
|
|
||||||
device_extensions: [ext_image_drm_format_modifier],
|
|
||||||
},
|
|
||||||
|
|
||||||
// TODO: document
|
|
||||||
memory_plane2 = MEMORY_PLANE_2_EXT {
|
|
||||||
device_extensions: [ext_image_drm_format_modifier],
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ImageAspects {
|
|
||||||
#[inline]
|
|
||||||
pub fn iter(&self) -> impl Iterator<Item = ImageAspect> {
|
|
||||||
let Self {
|
|
||||||
color,
|
|
||||||
depth,
|
|
||||||
stencil,
|
|
||||||
metadata,
|
|
||||||
plane0,
|
|
||||||
plane1,
|
|
||||||
plane2,
|
|
||||||
memory_plane0,
|
|
||||||
memory_plane1,
|
|
||||||
memory_plane2,
|
|
||||||
_ne: _,
|
|
||||||
} = *self;
|
|
||||||
|
|
||||||
[
|
|
||||||
color.then_some(ImageAspect::Color),
|
|
||||||
depth.then_some(ImageAspect::Depth),
|
|
||||||
stencil.then_some(ImageAspect::Stencil),
|
|
||||||
metadata.then_some(ImageAspect::Metadata),
|
|
||||||
plane0.then_some(ImageAspect::Plane0),
|
|
||||||
plane1.then_some(ImageAspect::Plane1),
|
|
||||||
plane2.then_some(ImageAspect::Plane2),
|
|
||||||
memory_plane0.then_some(ImageAspect::MemoryPlane0),
|
|
||||||
memory_plane1.then_some(ImageAspect::MemoryPlane1),
|
|
||||||
memory_plane2.then_some(ImageAspect::MemoryPlane2),
|
|
||||||
]
|
|
||||||
.into_iter()
|
|
||||||
.flatten()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<ImageAspect> for ImageAspects {
|
|
||||||
#[inline]
|
|
||||||
fn from(aspect: ImageAspect) -> Self {
|
|
||||||
let mut result = Self::empty();
|
|
||||||
|
|
||||||
match aspect {
|
|
||||||
ImageAspect::Color => result.color = true,
|
|
||||||
ImageAspect::Depth => result.depth = true,
|
|
||||||
ImageAspect::Stencil => result.stencil = true,
|
|
||||||
ImageAspect::Metadata => result.metadata = true,
|
|
||||||
ImageAspect::Plane0 => result.plane0 = true,
|
|
||||||
ImageAspect::Plane1 => result.plane1 = true,
|
|
||||||
ImageAspect::Plane2 => result.plane2 = true,
|
|
||||||
ImageAspect::MemoryPlane0 => result.memory_plane0 = true,
|
|
||||||
ImageAspect::MemoryPlane1 => result.memory_plane1 = true,
|
|
||||||
ImageAspect::MemoryPlane2 => result.memory_plane2 = true,
|
|
||||||
}
|
|
||||||
|
|
||||||
result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromIterator<ImageAspect> for ImageAspects {
|
|
||||||
fn from_iter<T: IntoIterator<Item = ImageAspect>>(iter: T) -> Self {
|
|
||||||
let mut result = Self::empty();
|
|
||||||
|
|
||||||
for aspect in iter {
|
|
||||||
match aspect {
|
|
||||||
ImageAspect::Color => result.color = true,
|
|
||||||
ImageAspect::Depth => result.depth = true,
|
|
||||||
ImageAspect::Stencil => result.stencil = true,
|
|
||||||
ImageAspect::Metadata => result.metadata = true,
|
|
||||||
ImageAspect::Plane0 => result.plane0 = true,
|
|
||||||
ImageAspect::Plane1 => result.plane1 = true,
|
|
||||||
ImageAspect::Plane2 => result.plane2 = true,
|
|
||||||
ImageAspect::MemoryPlane0 => result.memory_plane0 = true,
|
|
||||||
ImageAspect::MemoryPlane1 => result.memory_plane1 = true,
|
|
||||||
ImageAspect::MemoryPlane2 => result.memory_plane2 = true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -10,8 +10,8 @@
|
|||||||
use super::{
|
use super::{
|
||||||
sys::{Image, ImageMemory, RawImage},
|
sys::{Image, ImageMemory, RawImage},
|
||||||
traits::ImageContent,
|
traits::ImageContent,
|
||||||
ImageAccess, ImageDescriptorLayouts, ImageError, ImageInner, ImageLayout, ImageUsage,
|
ImageAccess, ImageAspects, ImageDescriptorLayouts, ImageError, ImageInner, ImageLayout,
|
||||||
SampleCount,
|
ImageUsage, SampleCount,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
device::{Device, DeviceOwned},
|
device::{Device, DeviceOwned},
|
||||||
@ -108,10 +108,7 @@ impl AttachmentImage {
|
|||||||
dimensions: [u32; 2],
|
dimensions: [u32; 2],
|
||||||
format: Format,
|
format: Format,
|
||||||
) -> Result<Arc<AttachmentImage>, ImageError> {
|
) -> Result<Arc<AttachmentImage>, ImageError> {
|
||||||
let base_usage = ImageUsage {
|
let base_usage = ImageUsage::INPUT_ATTACHMENT;
|
||||||
input_attachment: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
};
|
|
||||||
|
|
||||||
AttachmentImage::new_impl(
|
AttachmentImage::new_impl(
|
||||||
allocator,
|
allocator,
|
||||||
@ -154,10 +151,7 @@ impl AttachmentImage {
|
|||||||
samples: SampleCount,
|
samples: SampleCount,
|
||||||
format: Format,
|
format: Format,
|
||||||
) -> Result<Arc<AttachmentImage>, ImageError> {
|
) -> Result<Arc<AttachmentImage>, ImageError> {
|
||||||
let base_usage = ImageUsage {
|
let base_usage = ImageUsage::INPUT_ATTACHMENT;
|
||||||
input_attachment: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
};
|
|
||||||
|
|
||||||
AttachmentImage::new_impl(allocator, dimensions, 1, format, base_usage, samples)
|
AttachmentImage::new_impl(allocator, dimensions, 1, format, base_usage, samples)
|
||||||
}
|
}
|
||||||
@ -224,10 +218,7 @@ impl AttachmentImage {
|
|||||||
dimensions: [u32; 2],
|
dimensions: [u32; 2],
|
||||||
format: Format,
|
format: Format,
|
||||||
) -> Result<Arc<AttachmentImage>, ImageError> {
|
) -> Result<Arc<AttachmentImage>, ImageError> {
|
||||||
let base_usage = ImageUsage {
|
let base_usage = ImageUsage::SAMPLED;
|
||||||
sampled: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
};
|
|
||||||
|
|
||||||
AttachmentImage::new_impl(
|
AttachmentImage::new_impl(
|
||||||
allocator,
|
allocator,
|
||||||
@ -248,11 +239,7 @@ impl AttachmentImage {
|
|||||||
dimensions: [u32; 2],
|
dimensions: [u32; 2],
|
||||||
format: Format,
|
format: Format,
|
||||||
) -> Result<Arc<AttachmentImage>, ImageError> {
|
) -> Result<Arc<AttachmentImage>, ImageError> {
|
||||||
let base_usage = ImageUsage {
|
let base_usage = ImageUsage::SAMPLED | ImageUsage::INPUT_ATTACHMENT;
|
||||||
sampled: true,
|
|
||||||
input_attachment: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
};
|
|
||||||
|
|
||||||
AttachmentImage::new_impl(
|
AttachmentImage::new_impl(
|
||||||
allocator,
|
allocator,
|
||||||
@ -277,10 +264,7 @@ impl AttachmentImage {
|
|||||||
samples: SampleCount,
|
samples: SampleCount,
|
||||||
format: Format,
|
format: Format,
|
||||||
) -> Result<Arc<AttachmentImage>, ImageError> {
|
) -> Result<Arc<AttachmentImage>, ImageError> {
|
||||||
let base_usage = ImageUsage {
|
let base_usage = ImageUsage::SAMPLED;
|
||||||
sampled: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
};
|
|
||||||
|
|
||||||
AttachmentImage::new_impl(allocator, dimensions, 1, format, base_usage, samples)
|
AttachmentImage::new_impl(allocator, dimensions, 1, format, base_usage, samples)
|
||||||
}
|
}
|
||||||
@ -296,11 +280,7 @@ impl AttachmentImage {
|
|||||||
samples: SampleCount,
|
samples: SampleCount,
|
||||||
format: Format,
|
format: Format,
|
||||||
) -> Result<Arc<AttachmentImage>, ImageError> {
|
) -> Result<Arc<AttachmentImage>, ImageError> {
|
||||||
let base_usage = ImageUsage {
|
let base_usage = ImageUsage::SAMPLED | ImageUsage::INPUT_ATTACHMENT;
|
||||||
sampled: true,
|
|
||||||
input_attachment: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
};
|
|
||||||
|
|
||||||
AttachmentImage::new_impl(allocator, dimensions, 1, format, base_usage, samples)
|
AttachmentImage::new_impl(allocator, dimensions, 1, format, base_usage, samples)
|
||||||
}
|
}
|
||||||
@ -317,10 +297,7 @@ impl AttachmentImage {
|
|||||||
dimensions: [u32; 2],
|
dimensions: [u32; 2],
|
||||||
format: Format,
|
format: Format,
|
||||||
) -> Result<Arc<AttachmentImage>, ImageError> {
|
) -> Result<Arc<AttachmentImage>, ImageError> {
|
||||||
let base_usage = ImageUsage {
|
let base_usage = ImageUsage::TRANSIENT_ATTACHMENT;
|
||||||
transient_attachment: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
};
|
|
||||||
|
|
||||||
AttachmentImage::new_impl(
|
AttachmentImage::new_impl(
|
||||||
allocator,
|
allocator,
|
||||||
@ -341,11 +318,7 @@ impl AttachmentImage {
|
|||||||
dimensions: [u32; 2],
|
dimensions: [u32; 2],
|
||||||
format: Format,
|
format: Format,
|
||||||
) -> Result<Arc<AttachmentImage>, ImageError> {
|
) -> Result<Arc<AttachmentImage>, ImageError> {
|
||||||
let base_usage = ImageUsage {
|
let base_usage = ImageUsage::TRANSIENT_ATTACHMENT | ImageUsage::INPUT_ATTACHMENT;
|
||||||
transient_attachment: true,
|
|
||||||
input_attachment: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
};
|
|
||||||
|
|
||||||
AttachmentImage::new_impl(
|
AttachmentImage::new_impl(
|
||||||
allocator,
|
allocator,
|
||||||
@ -370,10 +343,7 @@ impl AttachmentImage {
|
|||||||
samples: SampleCount,
|
samples: SampleCount,
|
||||||
format: Format,
|
format: Format,
|
||||||
) -> Result<Arc<AttachmentImage>, ImageError> {
|
) -> Result<Arc<AttachmentImage>, ImageError> {
|
||||||
let base_usage = ImageUsage {
|
let base_usage = ImageUsage::TRANSIENT_ATTACHMENT;
|
||||||
transient_attachment: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
};
|
|
||||||
|
|
||||||
AttachmentImage::new_impl(allocator, dimensions, 1, format, base_usage, samples)
|
AttachmentImage::new_impl(allocator, dimensions, 1, format, base_usage, samples)
|
||||||
}
|
}
|
||||||
@ -389,11 +359,7 @@ impl AttachmentImage {
|
|||||||
samples: SampleCount,
|
samples: SampleCount,
|
||||||
format: Format,
|
format: Format,
|
||||||
) -> Result<Arc<AttachmentImage>, ImageError> {
|
) -> Result<Arc<AttachmentImage>, ImageError> {
|
||||||
let base_usage = ImageUsage {
|
let base_usage = ImageUsage::TRANSIENT_ATTACHMENT | ImageUsage::INPUT_ATTACHMENT;
|
||||||
transient_attachment: true,
|
|
||||||
input_attachment: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
};
|
|
||||||
|
|
||||||
AttachmentImage::new_impl(allocator, dimensions, 1, format, base_usage, samples)
|
AttachmentImage::new_impl(allocator, dimensions, 1, format, base_usage, samples)
|
||||||
}
|
}
|
||||||
@ -404,7 +370,7 @@ impl AttachmentImage {
|
|||||||
dimensions: [u32; 2],
|
dimensions: [u32; 2],
|
||||||
array_layers: u32,
|
array_layers: u32,
|
||||||
format: Format,
|
format: Format,
|
||||||
base_usage: ImageUsage,
|
mut usage: ImageUsage,
|
||||||
samples: SampleCount,
|
samples: SampleCount,
|
||||||
) -> Result<Arc<AttachmentImage>, ImageError> {
|
) -> Result<Arc<AttachmentImage>, ImageError> {
|
||||||
let physical_device = allocator.device().physical_device();
|
let physical_device = allocator.device().physical_device();
|
||||||
@ -421,7 +387,15 @@ impl AttachmentImage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let aspects = format.aspects();
|
let aspects = format.aspects();
|
||||||
let is_depth = aspects.depth || aspects.stencil;
|
let is_depth_stencil = aspects.intersects(ImageAspects::DEPTH | ImageAspects::STENCIL);
|
||||||
|
|
||||||
|
if is_depth_stencil {
|
||||||
|
usage -= ImageUsage::COLOR_ATTACHMENT;
|
||||||
|
usage |= ImageUsage::DEPTH_STENCIL_ATTACHMENT;
|
||||||
|
} else {
|
||||||
|
usage |= ImageUsage::COLOR_ATTACHMENT;
|
||||||
|
usage -= ImageUsage::DEPTH_STENCIL_ATTACHMENT;
|
||||||
|
}
|
||||||
|
|
||||||
if format.compression().is_some() {
|
if format.compression().is_some() {
|
||||||
panic!() // TODO: message?
|
panic!() // TODO: message?
|
||||||
@ -437,11 +411,7 @@ impl AttachmentImage {
|
|||||||
},
|
},
|
||||||
format: Some(format),
|
format: Some(format),
|
||||||
samples,
|
samples,
|
||||||
usage: ImageUsage {
|
usage,
|
||||||
color_attachment: !is_depth,
|
|
||||||
depth_stencil_attachment: is_depth,
|
|
||||||
..base_usage
|
|
||||||
},
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
@ -467,7 +437,7 @@ impl AttachmentImage {
|
|||||||
|
|
||||||
Ok(Arc::new(AttachmentImage {
|
Ok(Arc::new(AttachmentImage {
|
||||||
inner,
|
inner,
|
||||||
attachment_layout: if is_depth {
|
attachment_layout: if is_depth_stencil {
|
||||||
ImageLayout::DepthStencilAttachmentOptimal
|
ImageLayout::DepthStencilAttachmentOptimal
|
||||||
} else {
|
} else {
|
||||||
ImageLayout::ColorAttachmentOptimal
|
ImageLayout::ColorAttachmentOptimal
|
||||||
@ -484,7 +454,7 @@ impl AttachmentImage {
|
|||||||
dimensions: [u32; 2],
|
dimensions: [u32; 2],
|
||||||
array_layers: u32,
|
array_layers: u32,
|
||||||
format: Format,
|
format: Format,
|
||||||
base_usage: ImageUsage,
|
mut usage: ImageUsage,
|
||||||
samples: SampleCount,
|
samples: SampleCount,
|
||||||
) -> Result<Arc<AttachmentImage>, ImageError> {
|
) -> Result<Arc<AttachmentImage>, ImageError> {
|
||||||
let physical_device = allocator.device().physical_device();
|
let physical_device = allocator.device().physical_device();
|
||||||
@ -501,21 +471,21 @@ impl AttachmentImage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let aspects = format.aspects();
|
let aspects = format.aspects();
|
||||||
let is_depth = aspects.depth || aspects.stencil;
|
let is_depth_stencil = aspects.intersects(ImageAspects::DEPTH | ImageAspects::STENCIL);
|
||||||
let usage = ImageUsage {
|
|
||||||
color_attachment: !is_depth,
|
if is_depth_stencil {
|
||||||
depth_stencil_attachment: is_depth,
|
usage -= ImageUsage::COLOR_ATTACHMENT;
|
||||||
..base_usage
|
usage |= ImageUsage::DEPTH_STENCIL_ATTACHMENT;
|
||||||
};
|
} else {
|
||||||
|
usage |= ImageUsage::COLOR_ATTACHMENT;
|
||||||
|
usage -= ImageUsage::DEPTH_STENCIL_ATTACHMENT;
|
||||||
|
}
|
||||||
|
|
||||||
let external_memory_properties = allocator
|
let external_memory_properties = allocator
|
||||||
.device()
|
.device()
|
||||||
.physical_device()
|
.physical_device()
|
||||||
.image_format_properties(ImageFormatInfo {
|
.image_format_properties(ImageFormatInfo {
|
||||||
flags: ImageCreateFlags {
|
flags: ImageCreateFlags::MUTABLE_FORMAT,
|
||||||
mutable_format: true,
|
|
||||||
..ImageCreateFlags::empty()
|
|
||||||
},
|
|
||||||
format: Some(format),
|
format: Some(format),
|
||||||
usage,
|
usage,
|
||||||
external_memory_handle_type: Some(ExternalMemoryHandleType::OpaqueFd),
|
external_memory_handle_type: Some(ExternalMemoryHandleType::OpaqueFd),
|
||||||
@ -530,17 +500,11 @@ impl AttachmentImage {
|
|||||||
// VUID-VkMemoryAllocateInfo-pNext-00639
|
// VUID-VkMemoryAllocateInfo-pNext-00639
|
||||||
// Guaranteed because we always create a dedicated allocation
|
// Guaranteed because we always create a dedicated allocation
|
||||||
|
|
||||||
let external_memory_handle_types = ExternalMemoryHandleTypes {
|
let external_memory_handle_types = ExternalMemoryHandleTypes::OPAQUE_FD;
|
||||||
opaque_fd: true,
|
|
||||||
..ExternalMemoryHandleTypes::empty()
|
|
||||||
};
|
|
||||||
let raw_image = RawImage::new(
|
let raw_image = RawImage::new(
|
||||||
allocator.device().clone(),
|
allocator.device().clone(),
|
||||||
ImageCreateInfo {
|
ImageCreateInfo {
|
||||||
flags: ImageCreateFlags {
|
flags: ImageCreateFlags::MUTABLE_FORMAT,
|
||||||
mutable_format: true,
|
|
||||||
..ImageCreateFlags::empty()
|
|
||||||
},
|
|
||||||
dimensions: ImageDimensions::Dim2d {
|
dimensions: ImageDimensions::Dim2d {
|
||||||
width: dimensions[0],
|
width: dimensions[0],
|
||||||
height: dimensions[1],
|
height: dimensions[1],
|
||||||
@ -577,7 +541,7 @@ impl AttachmentImage {
|
|||||||
|
|
||||||
Ok(Arc::new(AttachmentImage {
|
Ok(Arc::new(AttachmentImage {
|
||||||
inner,
|
inner,
|
||||||
attachment_layout: if is_depth {
|
attachment_layout: if is_depth_stencil {
|
||||||
ImageLayout::DepthStencilAttachmentOptimal
|
ImageLayout::DepthStencilAttachmentOptimal
|
||||||
} else {
|
} else {
|
||||||
ImageLayout::ColorAttachmentOptimal
|
ImageLayout::ColorAttachmentOptimal
|
||||||
|
@ -115,7 +115,7 @@ impl ImmutableImage {
|
|||||||
) -> Result<(Arc<ImmutableImage>, Arc<ImmutableImageInitialization>), ImmutableImageCreationError>
|
) -> Result<(Arc<ImmutableImage>, Arc<ImmutableImageInitialization>), ImmutableImageCreationError>
|
||||||
{
|
{
|
||||||
let queue_family_indices: SmallVec<[_; 4]> = queue_family_indices.into_iter().collect();
|
let queue_family_indices: SmallVec<[_; 4]> = queue_family_indices.into_iter().collect();
|
||||||
assert!(!flags.disjoint); // TODO: adjust the code below to make this safe
|
assert!(!flags.intersects(ImageCreateFlags::DISJOINT)); // TODO: adjust the code below to make this safe
|
||||||
|
|
||||||
let raw_image = RawImage::new(
|
let raw_image = RawImage::new(
|
||||||
allocator.device().clone(),
|
allocator.device().clone(),
|
||||||
@ -188,15 +188,8 @@ impl ImmutableImage {
|
|||||||
I::IntoIter: ExactSizeIterator,
|
I::IntoIter: ExactSizeIterator,
|
||||||
A: CommandBufferAllocator,
|
A: CommandBufferAllocator,
|
||||||
{
|
{
|
||||||
let source = CpuAccessibleBuffer::from_iter(
|
let source =
|
||||||
allocator,
|
CpuAccessibleBuffer::from_iter(allocator, BufferUsage::TRANSFER_SRC, false, iter)?;
|
||||||
BufferUsage {
|
|
||||||
transfer_src: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
|
||||||
iter,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
ImmutableImage::from_buffer(
|
ImmutableImage::from_buffer(
|
||||||
allocator,
|
allocator,
|
||||||
@ -246,12 +239,13 @@ impl ImmutableImage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let need_to_generate_mipmaps = has_mipmaps(mip_levels);
|
let need_to_generate_mipmaps = has_mipmaps(mip_levels);
|
||||||
let usage = ImageUsage {
|
let usage = ImageUsage::TRANSFER_DST
|
||||||
transfer_dst: true,
|
| ImageUsage::SAMPLED
|
||||||
transfer_src: need_to_generate_mipmaps,
|
| if need_to_generate_mipmaps {
|
||||||
sampled: true,
|
ImageUsage::TRANSFER_SRC
|
||||||
..ImageUsage::empty()
|
} else {
|
||||||
};
|
ImageUsage::empty()
|
||||||
|
};
|
||||||
let flags = ImageCreateFlags::empty();
|
let flags = ImageCreateFlags::empty();
|
||||||
let layout = ImageLayout::ShaderReadOnlyOptimal;
|
let layout = ImageLayout::ShaderReadOnlyOptimal;
|
||||||
|
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
use crate::{descriptor_set::layout::DescriptorType, macros::vulkan_enum};
|
use crate::{descriptor_set::layout::DescriptorType, macros::vulkan_enum};
|
||||||
|
|
||||||
vulkan_enum! {
|
vulkan_enum! {
|
||||||
|
#[non_exhaustive]
|
||||||
|
|
||||||
/// In-memory layout of the pixel data of an image.
|
/// In-memory layout of the pixel data of an image.
|
||||||
///
|
///
|
||||||
/// The pixel data of a Vulkan image is arranged in a particular way, which is called its
|
/// The pixel data of a Vulkan image is arranged in a particular way, which is called its
|
||||||
@ -34,7 +36,6 @@ vulkan_enum! {
|
|||||||
/// user to specify which one. Vulkano helps with this by providing sensible defaults,
|
/// user to specify which one. Vulkano helps with this by providing sensible defaults,
|
||||||
/// automatically tracking the layout of each image when creating a command buffer, and adding
|
/// automatically tracking the layout of each image when creating a command buffer, and adding
|
||||||
/// layout transitions where needed.
|
/// layout transitions where needed.
|
||||||
#[non_exhaustive]
|
|
||||||
ImageLayout = ImageLayout(i32);
|
ImageLayout = ImageLayout(i32);
|
||||||
|
|
||||||
/// The layout of the data is unknown, and the image is treated as containing no valid data.
|
/// The layout of the data is unknown, and the image is treated as containing no valid data.
|
||||||
|
@ -60,7 +60,7 @@ pub use self::{
|
|||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
format::Format,
|
format::Format,
|
||||||
macros::{vulkan_bitflags, vulkan_enum},
|
macros::{vulkan_bitflags, vulkan_bitflags_enum, vulkan_enum},
|
||||||
memory::{ExternalMemoryHandleType, ExternalMemoryProperties},
|
memory::{ExternalMemoryHandleType, ExternalMemoryProperties},
|
||||||
DeviceSize,
|
DeviceSize,
|
||||||
};
|
};
|
||||||
@ -78,8 +78,9 @@ mod usage;
|
|||||||
pub mod view;
|
pub mod view;
|
||||||
|
|
||||||
vulkan_bitflags! {
|
vulkan_bitflags! {
|
||||||
/// Flags that can be set when creating a new image.
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
|
|
||||||
|
/// Flags that can be set when creating a new image.
|
||||||
ImageCreateFlags = ImageCreateFlags(u32);
|
ImageCreateFlags = ImageCreateFlags(u32);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -90,7 +91,7 @@ vulkan_bitflags! {
|
|||||||
///
|
///
|
||||||
/// [`bind_memory`]: sys::RawImage::bind_memory
|
/// [`bind_memory`]: sys::RawImage::bind_memory
|
||||||
/// [`sparse_binding`]: crate::device::Features::sparse_binding
|
/// [`sparse_binding`]: crate::device::Features::sparse_binding
|
||||||
sparse_binding = SPARSE_BINDING,
|
SPARSE_BINDING = SPARSE_BINDING,
|
||||||
|
|
||||||
/// The image can be used without being fully resident in memory at the time of use.
|
/// The image can be used without being fully resident in memory at the time of use.
|
||||||
///
|
///
|
||||||
@ -110,7 +111,7 @@ vulkan_bitflags! {
|
|||||||
/// [`sparse_residency4_samples`]: crate::device::Features::sparse_residency4_samples
|
/// [`sparse_residency4_samples`]: crate::device::Features::sparse_residency4_samples
|
||||||
/// [`sparse_residency8_samples`]: crate::device::Features::sparse_residency8_samples
|
/// [`sparse_residency8_samples`]: crate::device::Features::sparse_residency8_samples
|
||||||
/// [`sparse_residency16_samples`]: crate::device::Features::sparse_residency16_samples
|
/// [`sparse_residency16_samples`]: crate::device::Features::sparse_residency16_samples
|
||||||
sparse_residency = SPARSE_RESIDENCY,
|
SPARSE_RESIDENCY = SPARSE_RESIDENCY,
|
||||||
|
|
||||||
/// The buffer's memory can alias with another image or a different part of the same image.
|
/// The buffer's memory can alias with another image or a different part of the same image.
|
||||||
///
|
///
|
||||||
@ -119,7 +120,7 @@ vulkan_bitflags! {
|
|||||||
/// The [`sparse_residency_aliased`] feature must be enabled on the device.
|
/// The [`sparse_residency_aliased`] feature must be enabled on the device.
|
||||||
///
|
///
|
||||||
/// [`sparse_residency_aliased`]: crate::device::Features::sparse_residency_aliased
|
/// [`sparse_residency_aliased`]: crate::device::Features::sparse_residency_aliased
|
||||||
sparse_aliased = SPARSE_ALIASED,
|
SPARSE_ALIASED = SPARSE_ALIASED,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/// For non-multi-planar formats, whether an image view wrapping the image can have a
|
/// For non-multi-planar formats, whether an image view wrapping the image can have a
|
||||||
@ -127,24 +128,24 @@ vulkan_bitflags! {
|
|||||||
///
|
///
|
||||||
/// For multi-planar formats, whether an image view wrapping the image can be created from a
|
/// For multi-planar formats, whether an image view wrapping the image can be created from a
|
||||||
/// single plane of the image.
|
/// single plane of the image.
|
||||||
mutable_format = MUTABLE_FORMAT,
|
MUTABLE_FORMAT = MUTABLE_FORMAT,
|
||||||
|
|
||||||
/// For 2D images, whether an image view of type [`ImageViewType::Cube`] or
|
/// For 2D images, whether an image view of type [`ImageViewType::Cube`] or
|
||||||
/// [`ImageViewType::CubeArray`] can be created from the image.
|
/// [`ImageViewType::CubeArray`] can be created from the image.
|
||||||
///
|
///
|
||||||
/// [`ImageViewType::Cube`]: crate::image::view::ImageViewType::Cube
|
/// [`ImageViewType::Cube`]: crate::image::view::ImageViewType::Cube
|
||||||
/// [`ImageViewType::CubeArray`]: crate::image::view::ImageViewType::CubeArray
|
/// [`ImageViewType::CubeArray`]: crate::image::view::ImageViewType::CubeArray
|
||||||
cube_compatible = CUBE_COMPATIBLE,
|
CUBE_COMPATIBLE = CUBE_COMPATIBLE,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// TODO: document
|
// TODO: document
|
||||||
alias = ALIAS {
|
ALIAS = ALIAS {
|
||||||
api_version: V1_1,
|
api_version: V1_1,
|
||||||
device_extensions: [khr_bind_memory2],
|
device_extensions: [khr_bind_memory2],
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: document
|
// TODO: document
|
||||||
split_instance_bind_regions = SPLIT_INSTANCE_BIND_REGIONS {
|
SPLIT_INSTANCE_BIND_REGIONS = SPLIT_INSTANCE_BIND_REGIONS {
|
||||||
api_version: V1_1,
|
api_version: V1_1,
|
||||||
device_extensions: [khr_device_group],
|
device_extensions: [khr_device_group],
|
||||||
},
|
},
|
||||||
@ -160,7 +161,7 @@ vulkan_bitflags! {
|
|||||||
/// [`ImageViewType::Dim2dArray`]: crate::image::view::ImageViewType::Dim2dArray
|
/// [`ImageViewType::Dim2dArray`]: crate::image::view::ImageViewType::Dim2dArray
|
||||||
/// [portability subset]: crate::instance#portability-subset-devices-and-the-enumerate_portability-flag
|
/// [portability subset]: crate::instance#portability-subset-devices-and-the-enumerate_portability-flag
|
||||||
/// [`image_view2_d_on3_d_image`]: crate::device::Features::image_view2_d_on3_d_image
|
/// [`image_view2_d_on3_d_image`]: crate::device::Features::image_view2_d_on3_d_image
|
||||||
array_2d_compatible = TYPE_2D_ARRAY_COMPATIBLE {
|
ARRAY_2D_COMPATIBLE = TYPE_2D_ARRAY_COMPATIBLE {
|
||||||
api_version: V1_1,
|
api_version: V1_1,
|
||||||
device_extensions: [khr_maintenance1],
|
device_extensions: [khr_maintenance1],
|
||||||
},
|
},
|
||||||
@ -170,89 +171,115 @@ vulkan_bitflags! {
|
|||||||
/// compressed texel block in the image.
|
/// compressed texel block in the image.
|
||||||
///
|
///
|
||||||
/// Requires `mutable_format`.
|
/// Requires `mutable_format`.
|
||||||
block_texel_view_compatible = BLOCK_TEXEL_VIEW_COMPATIBLE {
|
BLOCK_TEXEL_VIEW_COMPATIBLE = BLOCK_TEXEL_VIEW_COMPATIBLE {
|
||||||
api_version: V1_1,
|
api_version: V1_1,
|
||||||
device_extensions: [khr_maintenance2],
|
device_extensions: [khr_maintenance2],
|
||||||
},
|
},
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// TODO: document
|
// TODO: document
|
||||||
extended_usage = EXTENDED_USAGE {
|
EXTENDED_USAGE = EXTENDED_USAGE {
|
||||||
api_version: V1_1,
|
api_version: V1_1,
|
||||||
device_extensions: [khr_maintenance2],
|
device_extensions: [khr_maintenance2],
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: document
|
// TODO: document
|
||||||
protected = PROTECTED {
|
PROTECTED = PROTECTED {
|
||||||
api_version: V1_1,
|
api_version: V1_1,
|
||||||
},
|
},
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/// For images with a multi-planar format, whether each plane will have its memory bound
|
/// For images with a multi-planar format, whether each plane will have its memory bound
|
||||||
/// separately, rather than having a single memory binding for the whole image.
|
/// separately, rather than having a single memory binding for the whole image.
|
||||||
disjoint = DISJOINT {
|
DISJOINT = DISJOINT {
|
||||||
api_version: V1_1,
|
api_version: V1_1,
|
||||||
device_extensions: [khr_sampler_ycbcr_conversion],
|
device_extensions: [khr_sampler_ycbcr_conversion],
|
||||||
},
|
},
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// TODO: document
|
// TODO: document
|
||||||
corner_sampled = CORNER_SAMPLED_NV {
|
CORNER_SAMPLED = CORNER_SAMPLED_NV {
|
||||||
device_extensions: [nv_corner_sampled_image],
|
device_extensions: [nv_corner_sampled_image],
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: document
|
// TODO: document
|
||||||
sample_locations_compatible_depth = SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_EXT {
|
SAMPLE_LOCATIONS_COMPATIBLE_DEPTH = SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_EXT {
|
||||||
device_extensions: [ext_sample_locations],
|
device_extensions: [ext_sample_locations],
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: document
|
// TODO: document
|
||||||
subsampled = SUBSAMPLED_EXT {
|
SUBSAMPLED = SUBSAMPLED_EXT {
|
||||||
device_extensions: [ext_fragment_density_map],
|
device_extensions: [ext_fragment_density_map],
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: document
|
// TODO: document
|
||||||
multisampled_render_to_single_sampled = MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_EXT {
|
MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED = MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_EXT {
|
||||||
device_extensions: [ext_multisampled_render_to_single_sampled],
|
device_extensions: [ext_multisampled_render_to_single_sampled],
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: document
|
// TODO: document
|
||||||
view_2d_compatible = TYPE_2D_VIEW_COMPATIBLE_EXT {
|
TYPE_2D_VIEW_COMPATIBLE = TYPE_2D_VIEW_COMPATIBLE_EXT {
|
||||||
device_extensions: [ext_image_2d_view_of_3d],
|
device_extensions: [ext_image_2d_view_of_3d],
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: document
|
// TODO: document
|
||||||
fragment_density_map_offset = FRAGMENT_DENSITY_MAP_OFFSET_QCOM {
|
FRAGMENT_DENSITY_MAP_OFFSET = FRAGMENT_DENSITY_MAP_OFFSET_QCOM {
|
||||||
device_extensions: [qcom_fragment_density_map_offset],
|
device_extensions: [qcom_fragment_density_map_offset],
|
||||||
},
|
},
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
vulkan_enum! {
|
vulkan_bitflags_enum! {
|
||||||
// TODO: document
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
SampleCount = SampleCountFlags(u32);
|
|
||||||
|
|
||||||
// TODO: document
|
/// A set of [`SampleCount`] values.
|
||||||
Sample1 = TYPE_1,
|
SampleCounts impl {
|
||||||
|
/// Returns the maximum sample count in `self`.
|
||||||
|
#[inline]
|
||||||
|
pub const fn max_count(self) -> SampleCount {
|
||||||
|
if self.intersects(SampleCounts::SAMPLE_64) {
|
||||||
|
SampleCount::Sample64
|
||||||
|
} else if self.intersects(SampleCounts::SAMPLE_32) {
|
||||||
|
SampleCount::Sample32
|
||||||
|
} else if self.intersects(SampleCounts::SAMPLE_16) {
|
||||||
|
SampleCount::Sample16
|
||||||
|
} else if self.intersects(SampleCounts::SAMPLE_8) {
|
||||||
|
SampleCount::Sample8
|
||||||
|
} else if self.intersects(SampleCounts::SAMPLE_4) {
|
||||||
|
SampleCount::Sample4
|
||||||
|
} else if self.intersects(SampleCounts::SAMPLE_2) {
|
||||||
|
SampleCount::Sample2
|
||||||
|
} else {
|
||||||
|
SampleCount::Sample1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
// TODO: document
|
/// The number of samples per texel of an image.
|
||||||
Sample2 = TYPE_2,
|
SampleCount,
|
||||||
|
|
||||||
// TODO: document
|
= SampleCountFlags(u32);
|
||||||
Sample4 = TYPE_4,
|
|
||||||
|
|
||||||
// TODO: document
|
/// 1 sample per texel.
|
||||||
Sample8 = TYPE_8,
|
SAMPLE_1, Sample1 = TYPE_1,
|
||||||
|
|
||||||
// TODO: document
|
/// 2 samples per texel.
|
||||||
Sample16 = TYPE_16,
|
SAMPLE_2, Sample2 = TYPE_2,
|
||||||
|
|
||||||
// TODO: document
|
/// 4 samples per texel.
|
||||||
Sample32 = TYPE_32,
|
SAMPLE_4, Sample4 = TYPE_4,
|
||||||
|
|
||||||
// TODO: document
|
/// 8 samples per texel.
|
||||||
Sample64 = TYPE_64,
|
SAMPLE_8, Sample8 = TYPE_8,
|
||||||
|
|
||||||
|
/// 16 samples per texel.
|
||||||
|
SAMPLE_16, Sample16 = TYPE_16,
|
||||||
|
|
||||||
|
/// 32 samples per texel.
|
||||||
|
SAMPLE_32, Sample32 = TYPE_32,
|
||||||
|
|
||||||
|
/// 64 samples per texel.
|
||||||
|
SAMPLE_64, Sample64 = TYPE_64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<u32> for SampleCount {
|
impl TryFrom<u32> for SampleCount {
|
||||||
@ -273,63 +300,6 @@ impl TryFrom<u32> for SampleCount {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vulkan_bitflags! {
|
|
||||||
/// Specifies a set of [`SampleCount`] values.
|
|
||||||
#[non_exhaustive]
|
|
||||||
SampleCounts = SampleCountFlags(u32);
|
|
||||||
|
|
||||||
/// 1 sample per pixel.
|
|
||||||
sample1 = TYPE_1,
|
|
||||||
|
|
||||||
/// 2 samples per pixel.
|
|
||||||
sample2 = TYPE_2,
|
|
||||||
|
|
||||||
/// 4 samples per pixel.
|
|
||||||
sample4 = TYPE_4,
|
|
||||||
|
|
||||||
/// 8 samples per pixel.
|
|
||||||
sample8 = TYPE_8,
|
|
||||||
|
|
||||||
/// 16 samples per pixel.
|
|
||||||
sample16 = TYPE_16,
|
|
||||||
|
|
||||||
/// 32 samples per pixel.
|
|
||||||
sample32 = TYPE_32,
|
|
||||||
|
|
||||||
/// 64 samples per pixel.
|
|
||||||
sample64 = TYPE_64,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SampleCounts {
|
|
||||||
/// Returns true if `self` has the `sample_count` value set.
|
|
||||||
#[inline]
|
|
||||||
pub const fn contains_count(&self, sample_count: SampleCount) -> bool {
|
|
||||||
match sample_count {
|
|
||||||
SampleCount::Sample1 => self.sample1,
|
|
||||||
SampleCount::Sample2 => self.sample2,
|
|
||||||
SampleCount::Sample4 => self.sample4,
|
|
||||||
SampleCount::Sample8 => self.sample8,
|
|
||||||
SampleCount::Sample16 => self.sample16,
|
|
||||||
SampleCount::Sample32 => self.sample32,
|
|
||||||
SampleCount::Sample64 => self.sample64,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the maximum sample count supported by `self`.
|
|
||||||
#[inline]
|
|
||||||
pub const fn max_count(&self) -> SampleCount {
|
|
||||||
match self {
|
|
||||||
Self { sample64: true, .. } => SampleCount::Sample64,
|
|
||||||
Self { sample32: true, .. } => SampleCount::Sample32,
|
|
||||||
Self { sample16: true, .. } => SampleCount::Sample16,
|
|
||||||
Self { sample8: true, .. } => SampleCount::Sample8,
|
|
||||||
Self { sample4: true, .. } => SampleCount::Sample4,
|
|
||||||
Self { sample2: true, .. } => SampleCount::Sample2,
|
|
||||||
_ => SampleCount::Sample1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Specifies how many mipmaps must be allocated.
|
/// Specifies how many mipmaps must be allocated.
|
||||||
///
|
///
|
||||||
/// Note that at least one mipmap must be allocated, to store the main level of the image.
|
/// Note that at least one mipmap must be allocated, to store the main level of the image.
|
||||||
@ -358,8 +328,9 @@ impl From<u32> for MipmapsCount {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vulkan_enum! {
|
vulkan_enum! {
|
||||||
// TODO: document
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
|
|
||||||
|
// TODO: document
|
||||||
ImageType = ImageType(i32);
|
ImageType = ImageType(i32);
|
||||||
|
|
||||||
// TODO: document
|
// TODO: document
|
||||||
@ -373,8 +344,9 @@ vulkan_enum! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vulkan_enum! {
|
vulkan_enum! {
|
||||||
// TODO: document
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
|
|
||||||
|
// TODO: document
|
||||||
ImageTiling = ImageTiling(i32);
|
ImageTiling = ImageTiling(i32);
|
||||||
|
|
||||||
// TODO: document
|
// TODO: document
|
||||||
@ -625,11 +597,8 @@ impl ImageSubresourceLayers {
|
|||||||
aspects: {
|
aspects: {
|
||||||
let aspects = format.aspects();
|
let aspects = format.aspects();
|
||||||
|
|
||||||
if aspects.plane0 {
|
if aspects.intersects(ImageAspects::PLANE_0) {
|
||||||
ImageAspects {
|
ImageAspects::PLANE_0
|
||||||
plane0: true,
|
|
||||||
..ImageAspects::empty()
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
aspects
|
aspects
|
||||||
}
|
}
|
||||||
@ -678,12 +647,8 @@ impl ImageSubresourceRange {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_parameters(format: Format, mip_levels: u32, array_layers: u32) -> Self {
|
pub fn from_parameters(format: Format, mip_levels: u32, array_layers: u32) -> Self {
|
||||||
Self {
|
Self {
|
||||||
aspects: ImageAspects {
|
aspects: format.aspects()
|
||||||
plane0: false,
|
- (ImageAspects::PLANE_0 | ImageAspects::PLANE_1 | ImageAspects::PLANE_2),
|
||||||
plane1: false,
|
|
||||||
plane2: false,
|
|
||||||
..format.aspects()
|
|
||||||
},
|
|
||||||
mip_levels: 0..mip_levels,
|
mip_levels: 0..mip_levels,
|
||||||
array_layers: 0..array_layers,
|
array_layers: 0..array_layers,
|
||||||
}
|
}
|
||||||
@ -946,19 +911,21 @@ pub struct SparseImageFormatProperties {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vulkan_bitflags! {
|
vulkan_bitflags! {
|
||||||
|
#[non_exhaustive]
|
||||||
|
|
||||||
/// Flags specifying information about a sparse resource.
|
/// Flags specifying information about a sparse resource.
|
||||||
SparseImageFormatFlags = SparseImageFormatFlags(u32);
|
SparseImageFormatFlags = SparseImageFormatFlags(u32);
|
||||||
|
|
||||||
/// The image uses a single mip tail region for all array layers, instead of one mip tail region
|
/// The image uses a single mip tail region for all array layers, instead of one mip tail region
|
||||||
/// per array layer.
|
/// per array layer.
|
||||||
single_miptail = SINGLE_MIPTAIL,
|
SINGLE_MIPTAIL = SINGLE_MIPTAIL,
|
||||||
|
|
||||||
/// The image's mip tail region begins with the first mip level whose dimensions are not an
|
/// The image's mip tail region begins with the first mip level whose dimensions are not an
|
||||||
/// integer multiple of the corresponding sparse image block dimensions.
|
/// integer multiple of the corresponding sparse image block dimensions.
|
||||||
aligned_mip_size = ALIGNED_MIP_SIZE,
|
ALIGNED_MIP_SIZE = ALIGNED_MIP_SIZE,
|
||||||
|
|
||||||
/// The image uses non-standard sparse image block dimensions.
|
/// The image uses non-standard sparse image block dimensions.
|
||||||
nonstandard_block_size = NONSTANDARD_BLOCK_SIZE,
|
NONSTANDARD_BLOCK_SIZE = NONSTANDARD_BLOCK_SIZE,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Requirements for binding memory to a sparse image.
|
/// Requirements for binding memory to a sparse image.
|
||||||
|
@ -10,8 +10,8 @@
|
|||||||
use super::{
|
use super::{
|
||||||
sys::{Image, ImageMemory, RawImage},
|
sys::{Image, ImageMemory, RawImage},
|
||||||
traits::ImageContent,
|
traits::ImageContent,
|
||||||
ImageAccess, ImageCreateFlags, ImageDescriptorLayouts, ImageDimensions, ImageError, ImageInner,
|
ImageAccess, ImageAspects, ImageCreateFlags, ImageDescriptorLayouts, ImageDimensions,
|
||||||
ImageLayout, ImageUsage,
|
ImageError, ImageInner, ImageLayout, ImageUsage,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
device::{Device, DeviceOwned, Queue},
|
device::{Device, DeviceOwned, Queue},
|
||||||
@ -51,22 +51,22 @@ impl StorageImage {
|
|||||||
queue_family_indices: impl IntoIterator<Item = u32>,
|
queue_family_indices: impl IntoIterator<Item = u32>,
|
||||||
) -> Result<Arc<StorageImage>, ImageError> {
|
) -> Result<Arc<StorageImage>, ImageError> {
|
||||||
let aspects = format.aspects();
|
let aspects = format.aspects();
|
||||||
let is_depth = aspects.depth || aspects.stencil;
|
let is_depth_stencil = aspects.intersects(ImageAspects::DEPTH | ImageAspects::STENCIL);
|
||||||
|
|
||||||
if format.compression().is_some() {
|
if format.compression().is_some() {
|
||||||
panic!() // TODO: message?
|
panic!() // TODO: message?
|
||||||
}
|
}
|
||||||
|
|
||||||
let usage = ImageUsage {
|
let usage = ImageUsage::TRANSFER_SRC
|
||||||
transfer_src: true,
|
| ImageUsage::TRANSFER_DST
|
||||||
transfer_dst: true,
|
| ImageUsage::SAMPLED
|
||||||
sampled: true,
|
| ImageUsage::STORAGE
|
||||||
storage: true,
|
| ImageUsage::INPUT_ATTACHMENT
|
||||||
color_attachment: !is_depth,
|
| if is_depth_stencil {
|
||||||
depth_stencil_attachment: is_depth,
|
ImageUsage::DEPTH_STENCIL_ATTACHMENT
|
||||||
input_attachment: true,
|
} else {
|
||||||
..ImageUsage::empty()
|
ImageUsage::COLOR_ATTACHMENT
|
||||||
};
|
};
|
||||||
let flags = ImageCreateFlags::empty();
|
let flags = ImageCreateFlags::empty();
|
||||||
|
|
||||||
StorageImage::with_usage(
|
StorageImage::with_usage(
|
||||||
@ -89,7 +89,7 @@ impl StorageImage {
|
|||||||
queue_family_indices: impl IntoIterator<Item = u32>,
|
queue_family_indices: impl IntoIterator<Item = u32>,
|
||||||
) -> Result<Arc<StorageImage>, ImageError> {
|
) -> Result<Arc<StorageImage>, ImageError> {
|
||||||
let queue_family_indices: SmallVec<[_; 4]> = queue_family_indices.into_iter().collect();
|
let queue_family_indices: SmallVec<[_; 4]> = queue_family_indices.into_iter().collect();
|
||||||
assert!(!flags.disjoint); // TODO: adjust the code below to make this safe
|
assert!(!flags.intersects(ImageCreateFlags::DISJOINT)); // TODO: adjust the code below to make this safe
|
||||||
|
|
||||||
let raw_image = RawImage::new(
|
let raw_image = RawImage::new(
|
||||||
allocator.device().clone(),
|
allocator.device().clone(),
|
||||||
@ -141,7 +141,7 @@ impl StorageImage {
|
|||||||
queue_family_indices: impl IntoIterator<Item = u32>,
|
queue_family_indices: impl IntoIterator<Item = u32>,
|
||||||
) -> Result<Arc<StorageImage>, ImageError> {
|
) -> Result<Arc<StorageImage>, ImageError> {
|
||||||
let queue_family_indices: SmallVec<[_; 4]> = queue_family_indices.into_iter().collect();
|
let queue_family_indices: SmallVec<[_; 4]> = queue_family_indices.into_iter().collect();
|
||||||
assert!(!flags.disjoint); // TODO: adjust the code below to make this safe
|
assert!(!flags.intersects(ImageCreateFlags::DISJOINT)); // TODO: adjust the code below to make this safe
|
||||||
|
|
||||||
let external_memory_properties = allocator
|
let external_memory_properties = allocator
|
||||||
.device()
|
.device()
|
||||||
@ -163,10 +163,7 @@ impl StorageImage {
|
|||||||
// VUID-VkMemoryAllocateInfo-pNext-00639
|
// VUID-VkMemoryAllocateInfo-pNext-00639
|
||||||
// Guaranteed because we always create a dedicated allocation
|
// Guaranteed because we always create a dedicated allocation
|
||||||
|
|
||||||
let external_memory_handle_types = ExternalMemoryHandleTypes {
|
let external_memory_handle_types = ExternalMemoryHandleTypes::OPAQUE_FD;
|
||||||
opaque_fd: true,
|
|
||||||
..ExternalMemoryHandleTypes::empty()
|
|
||||||
};
|
|
||||||
let raw_image = RawImage::new(
|
let raw_image = RawImage::new(
|
||||||
allocator.device().clone(),
|
allocator.device().clone(),
|
||||||
ImageCreateInfo {
|
ImageCreateInfo {
|
||||||
@ -360,12 +357,8 @@ mod tests {
|
|||||||
fn create_general_purpose_image_view() {
|
fn create_general_purpose_image_view() {
|
||||||
let (device, queue) = gfx_dev_and_queue!();
|
let (device, queue) = gfx_dev_and_queue!();
|
||||||
let memory_allocator = StandardMemoryAllocator::new_default(device);
|
let memory_allocator = StandardMemoryAllocator::new_default(device);
|
||||||
let usage = ImageUsage {
|
let usage =
|
||||||
transfer_src: true,
|
ImageUsage::TRANSFER_SRC | ImageUsage::TRANSFER_DST | ImageUsage::COLOR_ATTACHMENT;
|
||||||
transfer_dst: true,
|
|
||||||
color_attachment: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
};
|
|
||||||
let img_view = StorageImage::general_purpose_image_view(
|
let img_view = StorageImage::general_purpose_image_view(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
queue,
|
queue,
|
||||||
@ -374,7 +367,7 @@ mod tests {
|
|||||||
usage,
|
usage,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(img_view.image().usage(), &usage);
|
assert_eq!(img_view.image().usage(), usage);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -382,10 +375,7 @@ mod tests {
|
|||||||
let (device, queue) = gfx_dev_and_queue!();
|
let (device, queue) = gfx_dev_and_queue!();
|
||||||
let memory_allocator = StandardMemoryAllocator::new_default(device);
|
let memory_allocator = StandardMemoryAllocator::new_default(device);
|
||||||
// Not valid for image view...
|
// Not valid for image view...
|
||||||
let usage = ImageUsage {
|
let usage = ImageUsage::TRANSFER_SRC;
|
||||||
transfer_src: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
};
|
|
||||||
let img_result = StorageImage::general_purpose_image_view(
|
let img_result = StorageImage::general_purpose_image_view(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
queue,
|
queue,
|
||||||
|
@ -29,7 +29,8 @@ use crate::{
|
|||||||
},
|
},
|
||||||
memory::{
|
memory::{
|
||||||
allocator::{AllocationCreationError, MemoryAlloc},
|
allocator::{AllocationCreationError, MemoryAlloc},
|
||||||
DedicatedTo, ExternalMemoryHandleType, ExternalMemoryHandleTypes, MemoryRequirements,
|
DedicatedTo, ExternalMemoryHandleType, ExternalMemoryHandleTypes, MemoryPropertyFlags,
|
||||||
|
MemoryRequirements,
|
||||||
},
|
},
|
||||||
range_map::RangeMap,
|
range_map::RangeMap,
|
||||||
swapchain::Swapchain,
|
swapchain::Swapchain,
|
||||||
@ -140,13 +141,14 @@ impl RawImage {
|
|||||||
let format = format.unwrap(); // Can be None for "external formats" but Vulkano doesn't support that yet
|
let format = format.unwrap(); // Can be None for "external formats" but Vulkano doesn't support that yet
|
||||||
let aspects = format.aspects();
|
let aspects = format.aspects();
|
||||||
|
|
||||||
let has_separate_stencil_usage =
|
let has_separate_stencil_usage = if stencil_usage.is_empty()
|
||||||
if stencil_usage.is_empty() || !(aspects.depth && aspects.stencil) {
|
|| !aspects.contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
|
||||||
stencil_usage = usage;
|
{
|
||||||
false
|
stencil_usage = usage;
|
||||||
} else {
|
false
|
||||||
stencil_usage == usage
|
} else {
|
||||||
};
|
stencil_usage == usage
|
||||||
|
};
|
||||||
|
|
||||||
// VUID-VkImageCreateInfo-flags-parameter
|
// VUID-VkImageCreateInfo-flags-parameter
|
||||||
flags.validate_device(device)?;
|
flags.validate_device(device)?;
|
||||||
@ -171,7 +173,8 @@ impl RawImage {
|
|||||||
|| device.enabled_extensions().ext_separate_stencil_usage)
|
|| device.enabled_extensions().ext_separate_stencil_usage)
|
||||||
{
|
{
|
||||||
return Err(ImageError::RequirementNotMet {
|
return Err(ImageError::RequirementNotMet {
|
||||||
required_for: "`create_info.stencil_usage` is `Some` and `create_info.format` has both a depth and a stencil aspect",
|
required_for: "`create_info.stencil_usage` is `Some` and `create_info.format` \
|
||||||
|
has both a depth and a stencil aspect",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
api_version: Some(Version::V1_2),
|
api_version: Some(Version::V1_2),
|
||||||
device_extensions: &["ext_separate_stencil_usage"],
|
device_extensions: &["ext_separate_stencil_usage"],
|
||||||
@ -197,7 +200,10 @@ impl RawImage {
|
|||||||
));
|
));
|
||||||
|
|
||||||
// VUID-VkImageCreateInfo-flags-01573
|
// VUID-VkImageCreateInfo-flags-01573
|
||||||
assert!(!flags.block_texel_view_compatible || flags.mutable_format);
|
assert!(
|
||||||
|
!flags.intersects(ImageCreateFlags::BLOCK_TEXEL_VIEW_COMPATIBLE)
|
||||||
|
|| flags.intersects(ImageCreateFlags::MUTABLE_FORMAT)
|
||||||
|
);
|
||||||
|
|
||||||
// Get format features
|
// Get format features
|
||||||
let format_features = {
|
let format_features = {
|
||||||
@ -266,7 +272,7 @@ impl RawImage {
|
|||||||
return Err(ImageError::MultisampleNot2d);
|
return Err(ImageError::MultisampleNot2d);
|
||||||
}
|
}
|
||||||
|
|
||||||
if flags.cube_compatible {
|
if flags.intersects(ImageCreateFlags::CUBE_COMPATIBLE) {
|
||||||
return Err(ImageError::MultisampleCubeCompatible);
|
return Err(ImageError::MultisampleCubeCompatible);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,10 +290,9 @@ impl RawImage {
|
|||||||
&& array_layers != 1
|
&& array_layers != 1
|
||||||
{
|
{
|
||||||
return Err(ImageError::RequirementNotMet {
|
return Err(ImageError::RequirementNotMet {
|
||||||
required_for:
|
required_for: "this device is a portability subset device, \
|
||||||
"this device is a portability subset device, `create_info.samples` is not \
|
`create_info.samples` is not `SampleCount::Sample1` and \
|
||||||
`SampleCount::Sample1` and `create_info.dimensions.array_layers()` is \
|
`create_info.dimensions.array_layers()` is greater than `1`",
|
||||||
greater than `1`",
|
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["multisample_array_image"],
|
features: &["multisample_array_image"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -316,7 +321,8 @@ impl RawImage {
|
|||||||
// VUID-VkImageCreateInfo-format-06413
|
// VUID-VkImageCreateInfo-format-06413
|
||||||
if array_layers > 1 && !device.enabled_features().ycbcr_image_arrays {
|
if array_layers > 1 && !device.enabled_features().ycbcr_image_arrays {
|
||||||
return Err(ImageError::RequirementNotMet {
|
return Err(ImageError::RequirementNotMet {
|
||||||
required_for: "`create_info.format.ycbcr_chroma_sampling()` is `Some` and `create_info.dimensions.array_layers()` is greater than `1`",
|
required_for: "`create_info.format.ycbcr_chroma_sampling()` is `Some` and \
|
||||||
|
`create_info.dimensions.array_layers()` is greater than `1`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["ycbcr_image_arrays"],
|
features: &["ycbcr_image_arrays"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -346,35 +352,44 @@ impl RawImage {
|
|||||||
|
|
||||||
let combined_usage = usage | stencil_usage;
|
let combined_usage = usage | stencil_usage;
|
||||||
|
|
||||||
if combined_usage.sampled && !format_features.sampled_image {
|
if combined_usage.intersects(ImageUsage::SAMPLED)
|
||||||
|
&& !format_features.intersects(FormatFeatures::SAMPLED_IMAGE)
|
||||||
|
{
|
||||||
return Err(ImageError::FormatUsageNotSupported { usage: "sampled" });
|
return Err(ImageError::FormatUsageNotSupported { usage: "sampled" });
|
||||||
}
|
}
|
||||||
|
|
||||||
if combined_usage.color_attachment && !format_features.color_attachment {
|
if combined_usage.intersects(ImageUsage::COLOR_ATTACHMENT)
|
||||||
|
&& !format_features.intersects(FormatFeatures::COLOR_ATTACHMENT)
|
||||||
|
{
|
||||||
return Err(ImageError::FormatUsageNotSupported {
|
return Err(ImageError::FormatUsageNotSupported {
|
||||||
usage: "color_attachment",
|
usage: "color_attachment",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if combined_usage.depth_stencil_attachment && !format_features.depth_stencil_attachment {
|
if combined_usage.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
|
||||||
|
&& !format_features.intersects(FormatFeatures::DEPTH_STENCIL_ATTACHMENT)
|
||||||
|
{
|
||||||
return Err(ImageError::FormatUsageNotSupported {
|
return Err(ImageError::FormatUsageNotSupported {
|
||||||
usage: "depth_stencil_attachment",
|
usage: "depth_stencil_attachment",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if combined_usage.input_attachment
|
if combined_usage.intersects(ImageUsage::INPUT_ATTACHMENT)
|
||||||
&& !(format_features.color_attachment || format_features.depth_stencil_attachment)
|
&& !format_features.intersects(
|
||||||
|
FormatFeatures::COLOR_ATTACHMENT | FormatFeatures::DEPTH_STENCIL_ATTACHMENT,
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return Err(ImageError::FormatUsageNotSupported {
|
return Err(ImageError::FormatUsageNotSupported {
|
||||||
usage: "input_attachment",
|
usage: "input_attachment",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if combined_usage.color_attachment
|
if combined_usage.intersects(
|
||||||
|| combined_usage.depth_stencil_attachment
|
ImageUsage::COLOR_ATTACHMENT
|
||||||
|| combined_usage.input_attachment
|
| ImageUsage::DEPTH_STENCIL_ATTACHMENT
|
||||||
|| combined_usage.transient_attachment
|
| ImageUsage::INPUT_ATTACHMENT
|
||||||
{
|
| ImageUsage::TRANSIENT_ATTACHMENT,
|
||||||
|
) {
|
||||||
// VUID-VkImageCreateInfo-usage-00964
|
// VUID-VkImageCreateInfo-usage-00964
|
||||||
// VUID-VkImageCreateInfo-usage-00965
|
// VUID-VkImageCreateInfo-usage-00965
|
||||||
// VUID-VkImageCreateInfo-Format-02536
|
// VUID-VkImageCreateInfo-Format-02536
|
||||||
@ -392,8 +407,8 @@ impl RawImage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if combined_usage.storage {
|
if combined_usage.intersects(ImageUsage::STORAGE) {
|
||||||
if !format_features.storage_image {
|
if !format_features.intersects(FormatFeatures::STORAGE_IMAGE) {
|
||||||
return Err(ImageError::FormatUsageNotSupported { usage: "storage" });
|
return Err(ImageError::FormatUsageNotSupported { usage: "storage" });
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -403,7 +418,9 @@ impl RawImage {
|
|||||||
&& samples != SampleCount::Sample1
|
&& samples != SampleCount::Sample1
|
||||||
{
|
{
|
||||||
return Err(ImageError::RequirementNotMet {
|
return Err(ImageError::RequirementNotMet {
|
||||||
required_for: "`create_info.usage.storage` or `create_info.stencil_usage.storage` is set and `create_info.samples` is not `SampleCount::Sample1`",
|
required_for: "`create_info.usage` or `create_info.stencil_usage` contains \
|
||||||
|
`ImageUsage::STORAGE`, and `create_info.samples` is not \
|
||||||
|
`SampleCount::Sample1`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["shader_storage_image_multisample"],
|
features: &["shader_storage_image_multisample"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -414,40 +431,46 @@ impl RawImage {
|
|||||||
|
|
||||||
// These flags only exist in later versions, ignore them otherwise
|
// These flags only exist in later versions, ignore them otherwise
|
||||||
if device.api_version() >= Version::V1_1 || device.enabled_extensions().khr_maintenance1 {
|
if device.api_version() >= Version::V1_1 || device.enabled_extensions().khr_maintenance1 {
|
||||||
if combined_usage.transfer_src && !format_features.transfer_src {
|
if combined_usage.intersects(ImageUsage::TRANSFER_SRC)
|
||||||
|
&& !format_features.intersects(FormatFeatures::TRANSFER_SRC)
|
||||||
|
{
|
||||||
return Err(ImageError::FormatUsageNotSupported {
|
return Err(ImageError::FormatUsageNotSupported {
|
||||||
usage: "transfer_src",
|
usage: "transfer_src",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if combined_usage.transfer_dst && !format_features.transfer_dst {
|
if combined_usage.intersects(ImageUsage::TRANSFER_DST)
|
||||||
|
&& !format_features.intersects(FormatFeatures::TRANSFER_DST)
|
||||||
|
{
|
||||||
return Err(ImageError::FormatUsageNotSupported {
|
return Err(ImageError::FormatUsageNotSupported {
|
||||||
usage: "transfer_dst",
|
usage: "transfer_dst",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if usage.transient_attachment {
|
if usage.intersects(ImageUsage::TRANSIENT_ATTACHMENT) {
|
||||||
// VUID-VkImageCreateInfo-usage-00966
|
// VUID-VkImageCreateInfo-usage-00966
|
||||||
assert!(
|
assert!(usage.intersects(
|
||||||
usage.color_attachment || usage.depth_stencil_attachment || usage.input_attachment
|
ImageUsage::COLOR_ATTACHMENT
|
||||||
);
|
| ImageUsage::DEPTH_STENCIL_ATTACHMENT
|
||||||
|
| ImageUsage::INPUT_ATTACHMENT
|
||||||
|
));
|
||||||
|
|
||||||
// VUID-VkImageCreateInfo-usage-00963
|
// VUID-VkImageCreateInfo-usage-00963
|
||||||
assert!(ImageUsage {
|
assert!((usage
|
||||||
transient_attachment: false,
|
- (ImageUsage::TRANSIENT_ATTACHMENT
|
||||||
color_attachment: false,
|
| ImageUsage::COLOR_ATTACHMENT
|
||||||
depth_stencil_attachment: false,
|
| ImageUsage::DEPTH_STENCIL_ATTACHMENT
|
||||||
input_attachment: false,
|
| ImageUsage::INPUT_ATTACHMENT))
|
||||||
..usage
|
.is_empty())
|
||||||
}
|
|
||||||
.is_empty())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if has_separate_stencil_usage {
|
if has_separate_stencil_usage {
|
||||||
// VUID-VkImageCreateInfo-format-02795
|
// VUID-VkImageCreateInfo-format-02795
|
||||||
// VUID-VkImageCreateInfo-format-02796
|
// VUID-VkImageCreateInfo-format-02796
|
||||||
if usage.depth_stencil_attachment != stencil_usage.depth_stencil_attachment {
|
if usage.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
|
||||||
|
!= stencil_usage.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
|
||||||
|
{
|
||||||
return Err(ImageError::StencilUsageMismatch {
|
return Err(ImageError::StencilUsageMismatch {
|
||||||
usage,
|
usage,
|
||||||
stencil_usage,
|
stencil_usage,
|
||||||
@ -456,28 +479,28 @@ impl RawImage {
|
|||||||
|
|
||||||
// VUID-VkImageCreateInfo-format-02797
|
// VUID-VkImageCreateInfo-format-02797
|
||||||
// VUID-VkImageCreateInfo-format-02798
|
// VUID-VkImageCreateInfo-format-02798
|
||||||
if usage.transient_attachment != stencil_usage.transient_attachment {
|
if usage.intersects(ImageUsage::TRANSIENT_ATTACHMENT)
|
||||||
|
!= stencil_usage.intersects(ImageUsage::TRANSIENT_ATTACHMENT)
|
||||||
|
{
|
||||||
return Err(ImageError::StencilUsageMismatch {
|
return Err(ImageError::StencilUsageMismatch {
|
||||||
usage,
|
usage,
|
||||||
stencil_usage,
|
stencil_usage,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if stencil_usage.transient_attachment {
|
if stencil_usage.intersects(ImageUsage::TRANSIENT_ATTACHMENT) {
|
||||||
// VUID-VkImageStencilUsageCreateInfo-stencilUsage-02539
|
// VUID-VkImageStencilUsageCreateInfo-stencilUsage-02539
|
||||||
assert!(ImageUsage {
|
assert!((stencil_usage
|
||||||
transient_attachment: false,
|
- (ImageUsage::TRANSIENT_ATTACHMENT
|
||||||
depth_stencil_attachment: false,
|
| ImageUsage::DEPTH_STENCIL_ATTACHMENT
|
||||||
input_attachment: false,
|
| ImageUsage::INPUT_ATTACHMENT))
|
||||||
..stencil_usage
|
.is_empty())
|
||||||
}
|
|
||||||
.is_empty())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check flags requirements */
|
/* Check flags requirements */
|
||||||
|
|
||||||
if flags.cube_compatible {
|
if flags.intersects(ImageCreateFlags::CUBE_COMPATIBLE) {
|
||||||
// VUID-VkImageCreateInfo-flags-00949
|
// VUID-VkImageCreateInfo-flags-00949
|
||||||
if image_type != ImageType::Dim2d {
|
if image_type != ImageType::Dim2d {
|
||||||
return Err(ImageError::CubeCompatibleNot2d);
|
return Err(ImageError::CubeCompatibleNot2d);
|
||||||
@ -494,7 +517,7 @@ impl RawImage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if flags.array_2d_compatible {
|
if flags.intersects(ImageCreateFlags::ARRAY_2D_COMPATIBLE) {
|
||||||
// VUID-VkImageCreateInfo-flags-00950
|
// VUID-VkImageCreateInfo-flags-00950
|
||||||
if image_type != ImageType::Dim3d {
|
if image_type != ImageType::Dim3d {
|
||||||
return Err(ImageError::Array2dCompatibleNot3d);
|
return Err(ImageError::Array2dCompatibleNot3d);
|
||||||
@ -505,9 +528,8 @@ impl RawImage {
|
|||||||
&& !device.enabled_features().image_view2_d_on3_d_image
|
&& !device.enabled_features().image_view2_d_on3_d_image
|
||||||
{
|
{
|
||||||
return Err(ImageError::RequirementNotMet {
|
return Err(ImageError::RequirementNotMet {
|
||||||
required_for:
|
required_for: "this device is a portability subset device, and \
|
||||||
"this device is a portability subset device, and the `array_2d_compatible`
|
`create_info.flags` contains `ImageCreateFlags::ARRAY_2D_COMPATIBLE`",
|
||||||
flag is enabled",
|
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["image_view2_d_on3_d_image"],
|
features: &["image_view2_d_on3_d_image"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -516,21 +538,21 @@ impl RawImage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if flags.block_texel_view_compatible {
|
if flags.intersects(ImageCreateFlags::BLOCK_TEXEL_VIEW_COMPATIBLE) {
|
||||||
// VUID-VkImageCreateInfo-flags-01572
|
// VUID-VkImageCreateInfo-flags-01572
|
||||||
if format.compression().is_none() {
|
if format.compression().is_none() {
|
||||||
return Err(ImageError::BlockTexelViewCompatibleNotCompressed);
|
return Err(ImageError::BlockTexelViewCompatibleNotCompressed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if flags.disjoint {
|
if flags.intersects(ImageCreateFlags::DISJOINT) {
|
||||||
// VUID-VkImageCreateInfo-format-01577
|
// VUID-VkImageCreateInfo-format-01577
|
||||||
if format.planes().len() < 2 {
|
if format.planes().len() < 2 {
|
||||||
return Err(ImageError::DisjointFormatNotSupported);
|
return Err(ImageError::DisjointFormatNotSupported);
|
||||||
}
|
}
|
||||||
|
|
||||||
// VUID-VkImageCreateInfo-imageCreateFormatFeatures-02260
|
// VUID-VkImageCreateInfo-imageCreateFormatFeatures-02260
|
||||||
if !format_features.disjoint {
|
if !format_features.intersects(FormatFeatures::DISJOINT) {
|
||||||
return Err(ImageError::DisjointFormatNotSupported);
|
return Err(ImageError::DisjointFormatNotSupported);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -598,7 +620,7 @@ impl RawImage {
|
|||||||
let limit = device.physical_device().properties().max_image_dimension1_d;
|
let limit = device.physical_device().properties().max_image_dimension1_d;
|
||||||
extent[0] > limit
|
extent[0] > limit
|
||||||
}
|
}
|
||||||
ImageType::Dim2d if flags.cube_compatible => {
|
ImageType::Dim2d if flags.intersects(ImageCreateFlags::CUBE_COMPATIBLE) => {
|
||||||
let limit = device
|
let limit = device
|
||||||
.physical_device()
|
.physical_device()
|
||||||
.properties()
|
.properties()
|
||||||
@ -641,41 +663,41 @@ impl RawImage {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if combined_usage.color_attachment
|
if combined_usage.intersects(ImageUsage::COLOR_ATTACHMENT)
|
||||||
&& !device_properties
|
&& !device_properties
|
||||||
.framebuffer_color_sample_counts
|
.framebuffer_color_sample_counts
|
||||||
.contains_count(samples)
|
.contains_enum(samples)
|
||||||
{
|
{
|
||||||
// TODO: how to handle framebuffer_integer_color_sample_counts limit, which only
|
// TODO: how to handle framebuffer_integer_color_sample_counts limit, which only
|
||||||
// exists >= Vulkan 1.2
|
// exists >= Vulkan 1.2
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if combined_usage.depth_stencil_attachment {
|
if combined_usage.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT) {
|
||||||
if aspects.depth
|
if aspects.intersects(ImageAspects::DEPTH)
|
||||||
&& !device_properties
|
&& !device_properties
|
||||||
.framebuffer_depth_sample_counts
|
.framebuffer_depth_sample_counts
|
||||||
.contains_count(samples)
|
.contains_enum(samples)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if aspects.stencil
|
if aspects.intersects(ImageAspects::STENCIL)
|
||||||
&& !device_properties
|
&& !device_properties
|
||||||
.framebuffer_stencil_sample_counts
|
.framebuffer_stencil_sample_counts
|
||||||
.contains_count(samples)
|
.contains_enum(samples)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if combined_usage.sampled {
|
if combined_usage.intersects(ImageUsage::SAMPLED) {
|
||||||
if let Some(numeric_type) = format.type_color() {
|
if let Some(numeric_type) = format.type_color() {
|
||||||
match numeric_type {
|
match numeric_type {
|
||||||
NumericType::UINT | NumericType::SINT => {
|
NumericType::UINT | NumericType::SINT => {
|
||||||
if !device_properties
|
if !device_properties
|
||||||
.sampled_image_integer_sample_counts
|
.sampled_image_integer_sample_counts
|
||||||
.contains_count(samples)
|
.contains_enum(samples)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -689,35 +711,35 @@ impl RawImage {
|
|||||||
| NumericType::SRGB => {
|
| NumericType::SRGB => {
|
||||||
if !device_properties
|
if !device_properties
|
||||||
.sampled_image_color_sample_counts
|
.sampled_image_color_sample_counts
|
||||||
.contains_count(samples)
|
.contains_enum(samples)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if aspects.depth
|
if aspects.intersects(ImageAspects::DEPTH)
|
||||||
&& !device_properties
|
&& !device_properties
|
||||||
.sampled_image_depth_sample_counts
|
.sampled_image_depth_sample_counts
|
||||||
.contains_count(samples)
|
.contains_enum(samples)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if aspects.stencil
|
if aspects.intersects(ImageAspects::STENCIL)
|
||||||
&& device_properties
|
&& device_properties
|
||||||
.sampled_image_stencil_sample_counts
|
.sampled_image_stencil_sample_counts
|
||||||
.contains_count(samples)
|
.contains_enum(samples)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if combined_usage.storage
|
if combined_usage.intersects(ImageUsage::STORAGE)
|
||||||
&& !device_properties
|
&& !device_properties
|
||||||
.storage_image_sample_counts
|
.storage_image_sample_counts
|
||||||
.contains_count(samples)
|
.contains_enum(samples)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -733,11 +755,7 @@ impl RawImage {
|
|||||||
&& array_layers == 1
|
&& array_layers == 1
|
||||||
// VUID-VkImageCreateInfo-samples-02257 already states that multisampling+linear
|
// VUID-VkImageCreateInfo-samples-02257 already states that multisampling+linear
|
||||||
// is invalid so no need to check for that here.
|
// is invalid so no need to check for that here.
|
||||||
&& ImageUsage {
|
&& (usage - (ImageUsage::TRANSFER_SRC | ImageUsage::TRANSFER_DST)).is_empty())
|
||||||
transfer_src: false,
|
|
||||||
transfer_dst: false,
|
|
||||||
..usage
|
|
||||||
}.is_empty())
|
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
@ -756,7 +774,7 @@ impl RawImage {
|
|||||||
if !external_memory_handle_types.is_empty() {
|
if !external_memory_handle_types.is_empty() {
|
||||||
// If external memory handles are used, the properties need to be queried
|
// If external memory handles are used, the properties need to be queried
|
||||||
// individually for each handle type.
|
// individually for each handle type.
|
||||||
external_memory_handle_types.iter().map(Some).collect()
|
external_memory_handle_types.into_iter().map(Some).collect()
|
||||||
} else {
|
} else {
|
||||||
smallvec![None]
|
smallvec![None]
|
||||||
};
|
};
|
||||||
@ -819,7 +837,7 @@ impl RawImage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VUID-VkImageCreateInfo-samples-02258
|
// VUID-VkImageCreateInfo-samples-02258
|
||||||
if !sample_counts.contains_count(samples) {
|
if !sample_counts.contains_enum(samples) {
|
||||||
return Err(ImageError::SampleCountNotSupported {
|
return Err(ImageError::SampleCountNotSupported {
|
||||||
samples,
|
samples,
|
||||||
supported: sample_counts,
|
supported: sample_counts,
|
||||||
@ -856,13 +874,14 @@ impl RawImage {
|
|||||||
|
|
||||||
let aspects = format.map_or_else(Default::default, |format| format.aspects());
|
let aspects = format.map_or_else(Default::default, |format| format.aspects());
|
||||||
|
|
||||||
let has_separate_stencil_usage =
|
let has_separate_stencil_usage = if stencil_usage.is_empty()
|
||||||
if stencil_usage.is_empty() || !(aspects.depth && aspects.stencil) {
|
|| !aspects.contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
|
||||||
stencil_usage = usage;
|
{
|
||||||
false
|
stencil_usage = usage;
|
||||||
} else {
|
false
|
||||||
stencil_usage == usage
|
} else {
|
||||||
};
|
stencil_usage == usage
|
||||||
|
};
|
||||||
|
|
||||||
let (image_type, extent, array_layers) = match dimensions {
|
let (image_type, extent, array_layers) = match dimensions {
|
||||||
ImageDimensions::Dim1d {
|
ImageDimensions::Dim1d {
|
||||||
@ -984,7 +1003,9 @@ impl RawImage {
|
|||||||
|
|
||||||
let aspects = format.map_or_else(Default::default, |format| format.aspects());
|
let aspects = format.map_or_else(Default::default, |format| format.aspects());
|
||||||
|
|
||||||
if stencil_usage.is_empty() || !(aspects.depth && aspects.stencil) {
|
if stencil_usage.is_empty()
|
||||||
|
|| !aspects.contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
|
||||||
|
{
|
||||||
stencil_usage = usage;
|
stencil_usage = usage;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1001,7 +1022,7 @@ impl RawImage {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let memory_requirements = if flags.disjoint {
|
let memory_requirements = if flags.intersects(ImageCreateFlags::DISJOINT) {
|
||||||
(0..format.unwrap().planes().len())
|
(0..format.unwrap().planes().len())
|
||||||
.map(|plane| Self::get_memory_requirements(&device, handle, Some(plane)))
|
.map(|plane| Self::get_memory_requirements(&device, handle, Some(plane)))
|
||||||
.collect()
|
.collect()
|
||||||
@ -1342,7 +1363,7 @@ impl RawImage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn validate_bind_memory(&self, allocations: &[MemoryAlloc]) -> Result<(), ImageError> {
|
fn validate_bind_memory(&self, allocations: &[MemoryAlloc]) -> Result<(), ImageError> {
|
||||||
if self.flags.disjoint {
|
if self.flags.intersects(ImageCreateFlags::DISJOINT) {
|
||||||
if allocations.len() != self.format.unwrap().planes().len() {
|
if allocations.len() != self.format.unwrap().planes().len() {
|
||||||
return Err(ImageError::AllocationsWrongNumberOfElements {
|
return Err(ImageError::AllocationsWrongNumberOfElements {
|
||||||
provided: allocations.len(),
|
provided: allocations.len(),
|
||||||
@ -1398,7 +1419,10 @@ impl RawImage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VUID-VkBindImageMemoryInfo-None-01901
|
// VUID-VkBindImageMemoryInfo-None-01901
|
||||||
if memory_type.property_flags.protected {
|
if memory_type
|
||||||
|
.property_flags
|
||||||
|
.intersects(MemoryPropertyFlags::PROTECTED)
|
||||||
|
{
|
||||||
return Err(ImageError::MemoryProtectedMismatch {
|
return Err(ImageError::MemoryProtectedMismatch {
|
||||||
allocations_index,
|
allocations_index,
|
||||||
image_protected: false,
|
image_protected: false,
|
||||||
@ -1410,7 +1434,7 @@ impl RawImage {
|
|||||||
if !memory.export_handle_types().is_empty()
|
if !memory.export_handle_types().is_empty()
|
||||||
&& !memory
|
&& !memory
|
||||||
.export_handle_types()
|
.export_handle_types()
|
||||||
.intersects(&self.external_memory_handle_types)
|
.intersects(self.external_memory_handle_types)
|
||||||
{
|
{
|
||||||
return Err(ImageError::MemoryExternalHandleTypesDisjoint {
|
return Err(ImageError::MemoryExternalHandleTypesDisjoint {
|
||||||
allocations_index,
|
allocations_index,
|
||||||
@ -1422,7 +1446,7 @@ impl RawImage {
|
|||||||
if let Some(handle_type) = memory.imported_handle_type() {
|
if let Some(handle_type) = memory.imported_handle_type() {
|
||||||
// VUID-VkBindImageMemoryInfo-memory-02989
|
// VUID-VkBindImageMemoryInfo-memory-02989
|
||||||
if !ExternalMemoryHandleTypes::from(handle_type)
|
if !ExternalMemoryHandleTypes::from(handle_type)
|
||||||
.intersects(&self.external_memory_handle_types)
|
.intersects(self.external_memory_handle_types)
|
||||||
{
|
{
|
||||||
return Err(ImageError::MemoryImportedHandleTypeNotEnabled {
|
return Err(ImageError::MemoryImportedHandleTypeNotEnabled {
|
||||||
allocations_index,
|
allocations_index,
|
||||||
@ -1493,7 +1517,7 @@ impl RawImage {
|
|||||||
let mut infos_vk: SmallVec<[_; 3]> = SmallVec::with_capacity(3);
|
let mut infos_vk: SmallVec<[_; 3]> = SmallVec::with_capacity(3);
|
||||||
let mut plane_infos_vk: SmallVec<[_; 3]> = SmallVec::with_capacity(3);
|
let mut plane_infos_vk: SmallVec<[_; 3]> = SmallVec::with_capacity(3);
|
||||||
|
|
||||||
if self.flags.disjoint {
|
if self.flags.intersects(ImageCreateFlags::DISJOINT) {
|
||||||
debug_assert_eq!(allocations.len(), self.format.unwrap().planes().len());
|
debug_assert_eq!(allocations.len(), self.format.unwrap().planes().len());
|
||||||
|
|
||||||
for (plane, allocation) in allocations.iter().enumerate() {
|
for (plane, allocation) in allocations.iter().enumerate() {
|
||||||
@ -1602,8 +1626,8 @@ impl RawImage {
|
|||||||
|
|
||||||
/// Returns the features supported by the image's format.
|
/// Returns the features supported by the image's format.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn format_features(&self) -> &FormatFeatures {
|
pub fn format_features(&self) -> FormatFeatures {
|
||||||
&self.format_features
|
self.format_features
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the number of mipmap levels in the image.
|
/// Returns the number of mipmap levels in the image.
|
||||||
@ -1632,14 +1656,14 @@ impl RawImage {
|
|||||||
|
|
||||||
/// Returns the usage the image was created with.
|
/// Returns the usage the image was created with.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn usage(&self) -> &ImageUsage {
|
pub fn usage(&self) -> ImageUsage {
|
||||||
&self.usage
|
self.usage
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the stencil usage the image was created with.
|
/// Returns the stencil usage the image was created with.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn stencil_usage(&self) -> &ImageUsage {
|
pub fn stencil_usage(&self) -> ImageUsage {
|
||||||
&self.stencil_usage
|
self.stencil_usage
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the sharing the image was created with.
|
/// Returns the sharing the image was created with.
|
||||||
@ -1662,11 +1686,8 @@ impl RawImage {
|
|||||||
aspects: {
|
aspects: {
|
||||||
let aspects = self.format.unwrap().aspects();
|
let aspects = self.format.unwrap().aspects();
|
||||||
|
|
||||||
if aspects.plane0 {
|
if aspects.intersects(ImageAspects::PLANE_0) {
|
||||||
ImageAspects {
|
ImageAspects::PLANE_0
|
||||||
plane0: true,
|
|
||||||
..ImageAspects::empty()
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
aspects
|
aspects
|
||||||
}
|
}
|
||||||
@ -1681,12 +1702,8 @@ impl RawImage {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn subresource_range(&self) -> ImageSubresourceRange {
|
pub fn subresource_range(&self) -> ImageSubresourceRange {
|
||||||
ImageSubresourceRange {
|
ImageSubresourceRange {
|
||||||
aspects: ImageAspects {
|
aspects: self.format.unwrap().aspects()
|
||||||
plane0: false,
|
- (ImageAspects::PLANE_0 | ImageAspects::PLANE_1 | ImageAspects::PLANE_2),
|
||||||
plane1: false,
|
|
||||||
plane2: false,
|
|
||||||
..self.format.unwrap().aspects()
|
|
||||||
},
|
|
||||||
mip_levels: 0..self.mip_levels,
|
mip_levels: 0..self.mip_levels,
|
||||||
array_layers: 0..self.dimensions.array_layers(),
|
array_layers: 0..self.dimensions.array_layers(),
|
||||||
}
|
}
|
||||||
@ -1754,12 +1771,14 @@ impl RawImage {
|
|||||||
// VUID-vkGetImageSubresourceLayout-aspectMask-00997
|
// VUID-vkGetImageSubresourceLayout-aspectMask-00997
|
||||||
// VUID-vkGetImageSubresourceLayout-format-04462
|
// VUID-vkGetImageSubresourceLayout-format-04462
|
||||||
// VUID-vkGetImageSubresourceLayout-format-04463
|
// VUID-vkGetImageSubresourceLayout-format-04463
|
||||||
if allowed_aspects.depth && allowed_aspects.stencil {
|
if allowed_aspects.contains(ImageAspects::DEPTH | ImageAspects::STENCIL) {
|
||||||
return Err(ImageError::DepthStencilFormatsNotSupported);
|
return Err(ImageError::DepthStencilFormatsNotSupported);
|
||||||
}
|
}
|
||||||
|
|
||||||
if allowed_aspects.plane0 || allowed_aspects.plane1 || allowed_aspects.plane2 {
|
if allowed_aspects
|
||||||
allowed_aspects.color = false;
|
.intersects(ImageAspects::PLANE_0 | ImageAspects::PLANE_1 | ImageAspects::PLANE_2)
|
||||||
|
{
|
||||||
|
allowed_aspects -= ImageAspects::COLOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// VUID-vkGetImageSubresourceLayout-format-04461
|
// VUID-vkGetImageSubresourceLayout-format-04461
|
||||||
@ -1768,7 +1787,7 @@ impl RawImage {
|
|||||||
// VUID-vkGetImageSubresourceLayout-format-04464
|
// VUID-vkGetImageSubresourceLayout-format-04464
|
||||||
// VUID-vkGetImageSubresourceLayout-format-01581
|
// VUID-vkGetImageSubresourceLayout-format-01581
|
||||||
// VUID-vkGetImageSubresourceLayout-format-01582
|
// VUID-vkGetImageSubresourceLayout-format-01582
|
||||||
if !allowed_aspects.contains(&aspect.into()) {
|
if !allowed_aspects.contains(aspect.into()) {
|
||||||
return Err(ImageError::AspectNotAllowed {
|
return Err(ImageError::AspectNotAllowed {
|
||||||
provided_aspect: aspect,
|
provided_aspect: aspect,
|
||||||
allowed_aspects,
|
allowed_aspects,
|
||||||
@ -1997,7 +2016,7 @@ pub enum ImageMemory {
|
|||||||
impl Image {
|
impl Image {
|
||||||
fn from_raw(inner: RawImage, memory: ImageMemory) -> Self {
|
fn from_raw(inner: RawImage, memory: ImageMemory) -> Self {
|
||||||
let aspects = inner.format.unwrap().aspects();
|
let aspects = inner.format.unwrap().aspects();
|
||||||
let aspect_list: SmallVec<[ImageAspect; 4]> = aspects.iter().collect();
|
let aspect_list: SmallVec<[ImageAspect; 4]> = aspects.into_iter().collect();
|
||||||
let mip_level_size = inner.dimensions.array_layers() as DeviceSize;
|
let mip_level_size = inner.dimensions.array_layers() as DeviceSize;
|
||||||
let aspect_size = mip_level_size * inner.mip_levels as DeviceSize;
|
let aspect_size = mip_level_size * inner.mip_levels as DeviceSize;
|
||||||
let range_size = aspect_list.len() as DeviceSize * aspect_size;
|
let range_size = aspect_list.len() as DeviceSize * aspect_size;
|
||||||
@ -2088,8 +2107,8 @@ impl Image {
|
|||||||
|
|
||||||
/// Returns the features supported by the image's format.
|
/// Returns the features supported by the image's format.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn format_features(&self) -> &FormatFeatures {
|
pub fn format_features(&self) -> FormatFeatures {
|
||||||
&self.inner.format_features
|
self.inner.format_features
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the number of mipmap levels in the image.
|
/// Returns the number of mipmap levels in the image.
|
||||||
@ -2118,14 +2137,14 @@ impl Image {
|
|||||||
|
|
||||||
/// Returns the usage the image was created with.
|
/// Returns the usage the image was created with.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn usage(&self) -> &ImageUsage {
|
pub fn usage(&self) -> ImageUsage {
|
||||||
&self.inner.usage
|
self.inner.usage
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the stencil usage the image was created with.
|
/// Returns the stencil usage the image was created with.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn stencil_usage(&self) -> &ImageUsage {
|
pub fn stencil_usage(&self) -> ImageUsage {
|
||||||
&self.inner.stencil_usage
|
self.inner.stencil_usage
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the sharing the image was created with.
|
/// Returns the sharing the image was created with.
|
||||||
@ -2206,7 +2225,7 @@ impl Image {
|
|||||||
.format()
|
.format()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.aspects()
|
.aspects()
|
||||||
.contains(&subresource_range.aspects));
|
.contains(subresource_range.aspects));
|
||||||
assert!(subresource_range.mip_levels.end <= self.inner.mip_levels);
|
assert!(subresource_range.mip_levels.end <= self.inner.mip_levels);
|
||||||
assert!(subresource_range.array_layers.end <= self.inner.dimensions.array_layers());
|
assert!(subresource_range.array_layers.end <= self.inner.dimensions.array_layers());
|
||||||
|
|
||||||
@ -2608,7 +2627,7 @@ impl SubresourceRangeIterator {
|
|||||||
|
|
||||||
let mut aspect_nums = subresource_range
|
let mut aspect_nums = subresource_range
|
||||||
.aspects
|
.aspects
|
||||||
.iter()
|
.into_iter()
|
||||||
.map(|aspect| image_aspect_list.iter().position(|&a| a == aspect).unwrap())
|
.map(|aspect| image_aspect_list.iter().position(|&a| a == aspect).unwrap())
|
||||||
.collect::<SmallVec<[usize; 4]>>()
|
.collect::<SmallVec<[usize; 4]>>()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@ -3239,10 +3258,7 @@ mod tests {
|
|||||||
array_layers: 1,
|
array_layers: 1,
|
||||||
},
|
},
|
||||||
format: Some(Format::R8G8B8A8_UNORM),
|
format: Some(Format::R8G8B8A8_UNORM),
|
||||||
usage: ImageUsage {
|
usage: ImageUsage::SAMPLED,
|
||||||
sampled: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
},
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -3262,11 +3278,7 @@ mod tests {
|
|||||||
array_layers: 1,
|
array_layers: 1,
|
||||||
},
|
},
|
||||||
format: Some(Format::R8G8B8A8_UNORM),
|
format: Some(Format::R8G8B8A8_UNORM),
|
||||||
usage: ImageUsage {
|
usage: ImageUsage::TRANSIENT_ATTACHMENT | ImageUsage::COLOR_ATTACHMENT,
|
||||||
transient_attachment: true,
|
|
||||||
color_attachment: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
},
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -3288,10 +3300,7 @@ mod tests {
|
|||||||
},
|
},
|
||||||
format: Some(Format::R8G8B8A8_UNORM),
|
format: Some(Format::R8G8B8A8_UNORM),
|
||||||
mip_levels: 0,
|
mip_levels: 0,
|
||||||
usage: ImageUsage {
|
usage: ImageUsage::SAMPLED,
|
||||||
sampled: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
},
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -3312,10 +3321,7 @@ mod tests {
|
|||||||
},
|
},
|
||||||
format: Some(Format::R8G8B8A8_UNORM),
|
format: Some(Format::R8G8B8A8_UNORM),
|
||||||
mip_levels: u32::MAX,
|
mip_levels: u32::MAX,
|
||||||
usage: ImageUsage {
|
usage: ImageUsage::SAMPLED,
|
||||||
sampled: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
},
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -3340,10 +3346,7 @@ mod tests {
|
|||||||
},
|
},
|
||||||
format: Some(Format::R8G8B8A8_UNORM),
|
format: Some(Format::R8G8B8A8_UNORM),
|
||||||
samples: SampleCount::Sample2,
|
samples: SampleCount::Sample2,
|
||||||
usage: ImageUsage {
|
usage: ImageUsage::STORAGE,
|
||||||
storage: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
},
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -3371,10 +3374,7 @@ mod tests {
|
|||||||
array_layers: 1,
|
array_layers: 1,
|
||||||
},
|
},
|
||||||
format: Some(Format::ASTC_5x4_UNORM_BLOCK),
|
format: Some(Format::ASTC_5x4_UNORM_BLOCK),
|
||||||
usage: ImageUsage {
|
usage: ImageUsage::COLOR_ATTACHMENT,
|
||||||
color_attachment: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
},
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -3402,11 +3402,7 @@ mod tests {
|
|||||||
array_layers: 1,
|
array_layers: 1,
|
||||||
},
|
},
|
||||||
format: Some(Format::R8G8B8A8_UNORM),
|
format: Some(Format::R8G8B8A8_UNORM),
|
||||||
usage: ImageUsage {
|
usage: ImageUsage::TRANSIENT_ATTACHMENT | ImageUsage::SAMPLED,
|
||||||
transient_attachment: true,
|
|
||||||
sampled: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
},
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -3420,20 +3416,14 @@ mod tests {
|
|||||||
let res = RawImage::new(
|
let res = RawImage::new(
|
||||||
device,
|
device,
|
||||||
ImageCreateInfo {
|
ImageCreateInfo {
|
||||||
flags: ImageCreateFlags {
|
flags: ImageCreateFlags::CUBE_COMPATIBLE,
|
||||||
cube_compatible: true,
|
|
||||||
..ImageCreateFlags::empty()
|
|
||||||
},
|
|
||||||
dimensions: ImageDimensions::Dim2d {
|
dimensions: ImageDimensions::Dim2d {
|
||||||
width: 32,
|
width: 32,
|
||||||
height: 64,
|
height: 64,
|
||||||
array_layers: 1,
|
array_layers: 1,
|
||||||
},
|
},
|
||||||
format: Some(Format::R8G8B8A8_UNORM),
|
format: Some(Format::R8G8B8A8_UNORM),
|
||||||
usage: ImageUsage {
|
usage: ImageUsage::SAMPLED,
|
||||||
sampled: true,
|
|
||||||
..ImageUsage::empty()
|
|
||||||
},
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -3449,15 +3439,12 @@ mod tests {
|
|||||||
#[allow(clippy::erasing_op, clippy::identity_op)]
|
#[allow(clippy::erasing_op, clippy::identity_op)]
|
||||||
fn subresource_range_iterator() {
|
fn subresource_range_iterator() {
|
||||||
// A fictitious set of aspects that no real image would actually ever have.
|
// A fictitious set of aspects that no real image would actually ever have.
|
||||||
let image_aspect_list: SmallVec<[ImageAspect; 4]> = ImageAspects {
|
let image_aspect_list: SmallVec<[ImageAspect; 4]> = (ImageAspects::COLOR
|
||||||
color: true,
|
| ImageAspects::DEPTH
|
||||||
depth: true,
|
| ImageAspects::STENCIL
|
||||||
stencil: true,
|
| ImageAspects::PLANE_0)
|
||||||
plane0: true,
|
.into_iter()
|
||||||
..ImageAspects::empty()
|
.collect();
|
||||||
}
|
|
||||||
.iter()
|
|
||||||
.collect();
|
|
||||||
let image_mip_levels = 6;
|
let image_mip_levels = 6;
|
||||||
let image_array_layers = 8;
|
let image_array_layers = 8;
|
||||||
|
|
||||||
@ -3467,13 +3454,10 @@ mod tests {
|
|||||||
// Whole image
|
// Whole image
|
||||||
let mut iter = SubresourceRangeIterator::new(
|
let mut iter = SubresourceRangeIterator::new(
|
||||||
ImageSubresourceRange {
|
ImageSubresourceRange {
|
||||||
aspects: ImageAspects {
|
aspects: ImageAspects::COLOR
|
||||||
color: true,
|
| ImageAspects::DEPTH
|
||||||
depth: true,
|
| ImageAspects::STENCIL
|
||||||
stencil: true,
|
| ImageAspects::PLANE_0,
|
||||||
plane0: true,
|
|
||||||
..ImageAspects::empty()
|
|
||||||
},
|
|
||||||
mip_levels: 0..6,
|
mip_levels: 0..6,
|
||||||
array_layers: 0..8,
|
array_layers: 0..8,
|
||||||
},
|
},
|
||||||
@ -3490,13 +3474,7 @@ mod tests {
|
|||||||
// Only some aspects
|
// Only some aspects
|
||||||
let mut iter = SubresourceRangeIterator::new(
|
let mut iter = SubresourceRangeIterator::new(
|
||||||
ImageSubresourceRange {
|
ImageSubresourceRange {
|
||||||
aspects: ImageAspects {
|
aspects: ImageAspects::COLOR | ImageAspects::DEPTH | ImageAspects::PLANE_0,
|
||||||
color: true,
|
|
||||||
depth: true,
|
|
||||||
stencil: false,
|
|
||||||
plane0: true,
|
|
||||||
..ImageAspects::empty()
|
|
||||||
},
|
|
||||||
mip_levels: 0..6,
|
mip_levels: 0..6,
|
||||||
array_layers: 0..8,
|
array_layers: 0..8,
|
||||||
},
|
},
|
||||||
@ -3514,13 +3492,7 @@ mod tests {
|
|||||||
// Two aspects, and only some of the mip levels
|
// Two aspects, and only some of the mip levels
|
||||||
let mut iter = SubresourceRangeIterator::new(
|
let mut iter = SubresourceRangeIterator::new(
|
||||||
ImageSubresourceRange {
|
ImageSubresourceRange {
|
||||||
aspects: ImageAspects {
|
aspects: ImageAspects::DEPTH | ImageAspects::STENCIL,
|
||||||
color: false,
|
|
||||||
depth: true,
|
|
||||||
stencil: true,
|
|
||||||
plane0: false,
|
|
||||||
..ImageAspects::empty()
|
|
||||||
},
|
|
||||||
mip_levels: 2..4,
|
mip_levels: 2..4,
|
||||||
array_layers: 0..8,
|
array_layers: 0..8,
|
||||||
},
|
},
|
||||||
@ -3537,13 +3509,8 @@ mod tests {
|
|||||||
// One aspect, one mip level, only some of the array layers
|
// One aspect, one mip level, only some of the array layers
|
||||||
let mut iter = SubresourceRangeIterator::new(
|
let mut iter = SubresourceRangeIterator::new(
|
||||||
ImageSubresourceRange {
|
ImageSubresourceRange {
|
||||||
aspects: ImageAspects {
|
aspects: ImageAspects::COLOR,
|
||||||
color: true,
|
|
||||||
depth: false,
|
|
||||||
stencil: false,
|
|
||||||
plane0: false,
|
|
||||||
..ImageAspects::empty()
|
|
||||||
},
|
|
||||||
mip_levels: 0..1,
|
mip_levels: 0..1,
|
||||||
array_layers: 2..4,
|
array_layers: 2..4,
|
||||||
},
|
},
|
||||||
@ -3563,13 +3530,7 @@ mod tests {
|
|||||||
// Two aspects, two mip levels, only some of the array layers
|
// Two aspects, two mip levels, only some of the array layers
|
||||||
let mut iter = SubresourceRangeIterator::new(
|
let mut iter = SubresourceRangeIterator::new(
|
||||||
ImageSubresourceRange {
|
ImageSubresourceRange {
|
||||||
aspects: ImageAspects {
|
aspects: ImageAspects::DEPTH | ImageAspects::STENCIL,
|
||||||
color: false,
|
|
||||||
depth: true,
|
|
||||||
stencil: true,
|
|
||||||
plane0: false,
|
|
||||||
..ImageAspects::empty()
|
|
||||||
},
|
|
||||||
mip_levels: 2..4,
|
mip_levels: 2..4,
|
||||||
array_layers: 6..8,
|
array_layers: 6..8,
|
||||||
},
|
},
|
||||||
|
@ -75,7 +75,7 @@ pub unsafe trait ImageAccess: DeviceOwned + Send + Sync {
|
|||||||
|
|
||||||
/// Returns the features supported by the image's format.
|
/// Returns the features supported by the image's format.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn format_features(&self) -> &FormatFeatures {
|
fn format_features(&self) -> FormatFeatures {
|
||||||
self.inner().image.format_features()
|
self.inner().image.format_features()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,13 +93,13 @@ pub unsafe trait ImageAccess: DeviceOwned + Send + Sync {
|
|||||||
|
|
||||||
/// Returns the usage the image was created with.
|
/// Returns the usage the image was created with.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn usage(&self) -> &ImageUsage {
|
fn usage(&self) -> ImageUsage {
|
||||||
self.inner().image.usage()
|
self.inner().image.usage()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the stencil usage the image was created with.
|
/// Returns the stencil usage the image was created with.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn stencil_usage(&self) -> &ImageUsage {
|
fn stencil_usage(&self) -> ImageUsage {
|
||||||
self.inner().image.stencil_usage()
|
self.inner().image.stencil_usage()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,12 +115,8 @@ pub unsafe trait ImageAccess: DeviceOwned + Send + Sync {
|
|||||||
#[inline]
|
#[inline]
|
||||||
fn subresource_range(&self) -> ImageSubresourceRange {
|
fn subresource_range(&self) -> ImageSubresourceRange {
|
||||||
ImageSubresourceRange {
|
ImageSubresourceRange {
|
||||||
aspects: ImageAspects {
|
aspects: self.format().aspects()
|
||||||
plane0: false,
|
- (ImageAspects::PLANE_0 | ImageAspects::PLANE_1 | ImageAspects::PLANE_2),
|
||||||
plane1: false,
|
|
||||||
plane2: false,
|
|
||||||
..self.format().aspects()
|
|
||||||
},
|
|
||||||
mip_levels: 0..self.mip_levels(),
|
mip_levels: 0..self.mip_levels(),
|
||||||
array_layers: 0..self.dimensions().array_layers(),
|
array_layers: 0..self.dimensions().array_layers(),
|
||||||
}
|
}
|
||||||
|
@ -10,29 +10,30 @@
|
|||||||
use crate::macros::vulkan_bitflags;
|
use crate::macros::vulkan_bitflags;
|
||||||
|
|
||||||
vulkan_bitflags! {
|
vulkan_bitflags! {
|
||||||
|
#[non_exhaustive]
|
||||||
|
|
||||||
/// Describes how an image is going to be used. This is **not** just an optimization.
|
/// Describes how an image is going to be used. This is **not** just an optimization.
|
||||||
///
|
///
|
||||||
/// If you try to use an image in a way that you didn't declare, an error will occur.
|
/// If you try to use an image in a way that you didn't declare, an error will occur.
|
||||||
#[non_exhaustive]
|
|
||||||
ImageUsage = ImageUsageFlags(u32);
|
ImageUsage = ImageUsageFlags(u32);
|
||||||
|
|
||||||
/// The image can be used as a source for transfer, blit, resolve and clear commands.
|
/// The image can be used as a source for transfer, blit, resolve and clear commands.
|
||||||
transfer_src = TRANSFER_SRC,
|
TRANSFER_SRC = TRANSFER_SRC,
|
||||||
|
|
||||||
/// The image can be used as a destination for transfer, blit, resolve and clear commands.
|
/// The image can be used as a destination for transfer, blit, resolve and clear commands.
|
||||||
transfer_dst = TRANSFER_DST,
|
TRANSFER_DST = TRANSFER_DST,
|
||||||
|
|
||||||
/// The image can be used as a sampled image in a shader.
|
/// The image can be used as a sampled image in a shader.
|
||||||
sampled = SAMPLED,
|
SAMPLED = SAMPLED,
|
||||||
|
|
||||||
/// The image can be used as a storage image in a shader.
|
/// The image can be used as a storage image in a shader.
|
||||||
storage = STORAGE,
|
STORAGE = STORAGE,
|
||||||
|
|
||||||
/// The image can be used as a color attachment in a render pass/framebuffer.
|
/// The image can be used as a color attachment in a render pass/framebuffer.
|
||||||
color_attachment = COLOR_ATTACHMENT,
|
COLOR_ATTACHMENT = COLOR_ATTACHMENT,
|
||||||
|
|
||||||
/// The image can be used as a depth/stencil attachment in a render pass/framebuffer.
|
/// The image can be used as a depth/stencil attachment in a render pass/framebuffer.
|
||||||
depth_stencil_attachment = DEPTH_STENCIL_ATTACHMENT,
|
DEPTH_STENCIL_ATTACHMENT = DEPTH_STENCIL_ATTACHMENT,
|
||||||
|
|
||||||
/// The image will be used as an attachment, and will only ever be used temporarily.
|
/// The image will be used as an attachment, and will only ever be used temporarily.
|
||||||
/// As soon as you leave a render pass, the content of transient images becomes undefined.
|
/// As soon as you leave a render pass, the content of transient images becomes undefined.
|
||||||
@ -43,54 +44,54 @@ vulkan_bitflags! {
|
|||||||
/// If `transient_attachment` is true, then only `color_attachment`, `depth_stencil_attachment`
|
/// If `transient_attachment` is true, then only `color_attachment`, `depth_stencil_attachment`
|
||||||
/// and `input_attachment` can be true as well. The rest must be false or an error will be
|
/// and `input_attachment` can be true as well. The rest must be false or an error will be
|
||||||
/// returned when creating the image.
|
/// returned when creating the image.
|
||||||
transient_attachment = TRANSIENT_ATTACHMENT,
|
TRANSIENT_ATTACHMENT = TRANSIENT_ATTACHMENT,
|
||||||
|
|
||||||
/// The image can be used as an input attachment in a render pass/framebuffer.
|
/// The image can be used as an input attachment in a render pass/framebuffer.
|
||||||
input_attachment = INPUT_ATTACHMENT,
|
INPUT_ATTACHMENT = INPUT_ATTACHMENT,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// TODO: document
|
// TODO: document
|
||||||
video_decode_dst = VIDEO_DECODE_DST_KHR {
|
VIDEO_DECODE_DST = VIDEO_DECODE_DST_KHR {
|
||||||
device_extensions: [khr_video_decode_queue],
|
device_extensions: [khr_video_decode_queue],
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: document
|
// TODO: document
|
||||||
video_decode_src = VIDEO_DECODE_SRC_KHR {
|
VIDEO_DECODE_SRC = VIDEO_DECODE_SRC_KHR {
|
||||||
device_extensions: [khr_video_decode_queue],
|
device_extensions: [khr_video_decode_queue],
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: document
|
// TODO: document
|
||||||
video_decode_dpb = VIDEO_DECODE_DPB_KHR {
|
VIDEO_DECODE_DPB = VIDEO_DECODE_DPB_KHR {
|
||||||
device_extensions: [khr_video_decode_queue],
|
device_extensions: [khr_video_decode_queue],
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: document
|
// TODO: document
|
||||||
fragment_density_map = FRAGMENT_DENSITY_MAP_EXT {
|
FRAGMENT_DENSITY_MAP = FRAGMENT_DENSITY_MAP_EXT {
|
||||||
device_extensions: [ext_fragment_density_map],
|
device_extensions: [ext_fragment_density_map],
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: document
|
// TODO: document
|
||||||
fragment_shading_rate_attachment = FRAGMENT_SHADING_RATE_ATTACHMENT_KHR {
|
FRAGMENT_SHADING_RATE_ATTACHMENT = FRAGMENT_SHADING_RATE_ATTACHMENT_KHR {
|
||||||
device_extensions: [khr_fragment_shading_rate],
|
device_extensions: [khr_fragment_shading_rate],
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: document
|
// TODO: document
|
||||||
video_encode_dst = VIDEO_ENCODE_DST_KHR {
|
VIDEO_ENCODE_DST = VIDEO_ENCODE_DST_KHR {
|
||||||
device_extensions: [khr_video_encode_queue],
|
device_extensions: [khr_video_encode_queue],
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: document
|
// TODO: document
|
||||||
video_encode_src = VIDEO_ENCODE_SRC_KHR {
|
VIDEO_ENCODE_SRC = VIDEO_ENCODE_SRC_KHR {
|
||||||
device_extensions: [khr_video_encode_queue],
|
device_extensions: [khr_video_encode_queue],
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: document
|
// TODO: document
|
||||||
video_encode_dpb = VIDEO_ENCODE_DPB_KHR {
|
VIDEO_ENCODE_DPB = VIDEO_ENCODE_DPB_KHR {
|
||||||
device_extensions: [khr_video_encode_queue],
|
device_extensions: [khr_video_encode_queue],
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: document
|
// TODO: document
|
||||||
invocation_mask = INVOCATION_MASK_HUAWEI {
|
INVOCATION_MASK = INVOCATION_MASK_HUAWEI {
|
||||||
device_extensions: [huawei_invocation_mask],
|
device_extensions: [huawei_invocation_mask],
|
||||||
},
|
},
|
||||||
*/
|
*/
|
||||||
|
@ -19,7 +19,7 @@ use super::{
|
|||||||
use crate::{
|
use crate::{
|
||||||
device::{Device, DeviceOwned},
|
device::{Device, DeviceOwned},
|
||||||
format::{ChromaSampling, Format, FormatFeatures},
|
format::{ChromaSampling, Format, FormatFeatures},
|
||||||
image::{ImageAspects, ImageTiling, ImageType, SampleCount},
|
image::{ImageAspects, ImageCreateFlags, ImageTiling, ImageType, SampleCount},
|
||||||
macros::vulkan_enum,
|
macros::vulkan_enum,
|
||||||
sampler::{ycbcr::SamplerYcbcrConversion, ComponentMapping},
|
sampler::{ycbcr::SamplerYcbcrConversion, ComponentMapping},
|
||||||
OomError, RequirementNotMet, RequiresOneOf, Version, VulkanError, VulkanObject,
|
OomError, RequirementNotMet, RequiresOneOf, Version, VulkanError, VulkanObject,
|
||||||
@ -145,32 +145,24 @@ where
|
|||||||
// VUID-VkImageSubresourceRange-aspectMask-parameter
|
// VUID-VkImageSubresourceRange-aspectMask-parameter
|
||||||
subresource_range.aspects.validate_device(device)?;
|
subresource_range.aspects.validate_device(device)?;
|
||||||
|
|
||||||
{
|
assert!(!subresource_range.aspects.intersects(
|
||||||
let ImageAspects {
|
ImageAspects::METADATA
|
||||||
color,
|
| ImageAspects::MEMORY_PLANE_0
|
||||||
depth,
|
| ImageAspects::MEMORY_PLANE_1
|
||||||
stencil,
|
| ImageAspects::MEMORY_PLANE_2
|
||||||
metadata,
|
));
|
||||||
plane0,
|
assert!({
|
||||||
plane1,
|
subresource_range.aspects.count() == 1
|
||||||
plane2,
|
|| subresource_range
|
||||||
memory_plane0,
|
.aspects
|
||||||
memory_plane1,
|
.contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
|
||||||
memory_plane2,
|
&& !subresource_range.aspects.intersects(
|
||||||
_ne: _,
|
ImageAspects::COLOR
|
||||||
} = subresource_range.aspects;
|
| ImageAspects::PLANE_0
|
||||||
|
| ImageAspects::PLANE_1
|
||||||
assert!(!(metadata || memory_plane0 || memory_plane1 || memory_plane2));
|
| ImageAspects::PLANE_2,
|
||||||
assert!({
|
)
|
||||||
let num_bits = color as u8
|
});
|
||||||
+ depth as u8
|
|
||||||
+ stencil as u8
|
|
||||||
+ plane0 as u8
|
|
||||||
+ plane1 as u8
|
|
||||||
+ plane2 as u8;
|
|
||||||
num_bits == 1 || depth && stencil && !(color || plane0 || plane1 || plane2)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get format features
|
// Get format features
|
||||||
let format_features = unsafe { Self::get_format_features(format, image_inner) };
|
let format_features = unsafe { Self::get_format_features(format, image_inner) };
|
||||||
@ -180,7 +172,7 @@ where
|
|||||||
.format()
|
.format()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.aspects()
|
.aspects()
|
||||||
.contains(&subresource_range.aspects)
|
.contains(subresource_range.aspects)
|
||||||
{
|
{
|
||||||
return Err(ImageViewCreationError::ImageAspectsNotCompatible {
|
return Err(ImageViewCreationError::ImageAspectsNotCompatible {
|
||||||
aspects: subresource_range.aspects,
|
aspects: subresource_range.aspects,
|
||||||
@ -203,7 +195,9 @@ where
|
|||||||
|
|
||||||
// VUID-VkImageViewCreateInfo-image-01003
|
// VUID-VkImageViewCreateInfo-image-01003
|
||||||
if (view_type == ImageViewType::Cube || view_type == ImageViewType::CubeArray)
|
if (view_type == ImageViewType::Cube || view_type == ImageViewType::CubeArray)
|
||||||
&& !image_inner.flags().cube_compatible
|
&& !image_inner
|
||||||
|
.flags()
|
||||||
|
.intersects(ImageCreateFlags::CUBE_COMPATIBLE)
|
||||||
{
|
{
|
||||||
return Err(ImageViewCreationError::ImageNotCubeCompatible);
|
return Err(ImageViewCreationError::ImageNotCubeCompatible);
|
||||||
}
|
}
|
||||||
@ -231,7 +225,10 @@ where
|
|||||||
&& (view_type == ImageViewType::Dim2d || view_type == ImageViewType::Dim2dArray)
|
&& (view_type == ImageViewType::Dim2d || view_type == ImageViewType::Dim2dArray)
|
||||||
{
|
{
|
||||||
// VUID-VkImageViewCreateInfo-image-01005
|
// VUID-VkImageViewCreateInfo-image-01005
|
||||||
if !image_inner.flags().array_2d_compatible {
|
if !image_inner
|
||||||
|
.flags()
|
||||||
|
.intersects(ImageCreateFlags::ARRAY_2D_COMPATIBLE)
|
||||||
|
{
|
||||||
return Err(ImageViewCreationError::ImageNotArray2dCompatible);
|
return Err(ImageViewCreationError::ImageNotArray2dCompatible);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -299,7 +296,7 @@ where
|
|||||||
// VUID-VkImageViewCreateInfo-pNext-02662
|
// VUID-VkImageViewCreateInfo-pNext-02662
|
||||||
// VUID-VkImageViewCreateInfo-pNext-02663
|
// VUID-VkImageViewCreateInfo-pNext-02663
|
||||||
// VUID-VkImageViewCreateInfo-pNext-02664
|
// VUID-VkImageViewCreateInfo-pNext-02664
|
||||||
if !default_usage.contains(&usage) {
|
if !default_usage.contains(usage) {
|
||||||
return Err(ImageViewCreationError::UsageNotSupportedByImage {
|
return Err(ImageViewCreationError::UsageNotSupportedByImage {
|
||||||
usage,
|
usage,
|
||||||
supported_usage: default_usage,
|
supported_usage: default_usage,
|
||||||
@ -308,43 +305,54 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VUID-VkImageViewCreateInfo-image-04441
|
// VUID-VkImageViewCreateInfo-image-04441
|
||||||
if !(image_inner.usage().sampled
|
if !image_inner.usage().intersects(
|
||||||
|| image_inner.usage().storage
|
ImageUsage::SAMPLED
|
||||||
|| image_inner.usage().color_attachment
|
| ImageUsage::STORAGE
|
||||||
|| image_inner.usage().depth_stencil_attachment
|
| ImageUsage::COLOR_ATTACHMENT
|
||||||
|| image_inner.usage().input_attachment
|
| ImageUsage::DEPTH_STENCIL_ATTACHMENT
|
||||||
|| image_inner.usage().transient_attachment)
|
| ImageUsage::INPUT_ATTACHMENT
|
||||||
{
|
| ImageUsage::TRANSIENT_ATTACHMENT,
|
||||||
|
) {
|
||||||
return Err(ImageViewCreationError::ImageMissingUsage);
|
return Err(ImageViewCreationError::ImageMissingUsage);
|
||||||
}
|
}
|
||||||
|
|
||||||
// VUID-VkImageViewCreateInfo-usage-02274
|
// VUID-VkImageViewCreateInfo-usage-02274
|
||||||
if usage.sampled && !format_features.sampled_image {
|
if usage.intersects(ImageUsage::SAMPLED)
|
||||||
|
&& !format_features.intersects(FormatFeatures::SAMPLED_IMAGE)
|
||||||
|
{
|
||||||
return Err(ImageViewCreationError::FormatUsageNotSupported { usage: "sampled" });
|
return Err(ImageViewCreationError::FormatUsageNotSupported { usage: "sampled" });
|
||||||
}
|
}
|
||||||
|
|
||||||
// VUID-VkImageViewCreateInfo-usage-02275
|
// VUID-VkImageViewCreateInfo-usage-02275
|
||||||
if usage.storage && !format_features.storage_image {
|
if usage.intersects(ImageUsage::STORAGE)
|
||||||
|
&& !format_features.intersects(FormatFeatures::STORAGE_IMAGE)
|
||||||
|
{
|
||||||
return Err(ImageViewCreationError::FormatUsageNotSupported { usage: "storage" });
|
return Err(ImageViewCreationError::FormatUsageNotSupported { usage: "storage" });
|
||||||
}
|
}
|
||||||
|
|
||||||
// VUID-VkImageViewCreateInfo-usage-02276
|
// VUID-VkImageViewCreateInfo-usage-02276
|
||||||
if usage.color_attachment && !format_features.color_attachment {
|
if usage.intersects(ImageUsage::COLOR_ATTACHMENT)
|
||||||
|
&& !format_features.intersects(FormatFeatures::COLOR_ATTACHMENT)
|
||||||
|
{
|
||||||
return Err(ImageViewCreationError::FormatUsageNotSupported {
|
return Err(ImageViewCreationError::FormatUsageNotSupported {
|
||||||
usage: "color_attachment",
|
usage: "color_attachment",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// VUID-VkImageViewCreateInfo-usage-02277
|
// VUID-VkImageViewCreateInfo-usage-02277
|
||||||
if usage.depth_stencil_attachment && !format_features.depth_stencil_attachment {
|
if usage.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
|
||||||
|
&& !format_features.intersects(FormatFeatures::DEPTH_STENCIL_ATTACHMENT)
|
||||||
|
{
|
||||||
return Err(ImageViewCreationError::FormatUsageNotSupported {
|
return Err(ImageViewCreationError::FormatUsageNotSupported {
|
||||||
usage: "depth_stencil_attachment",
|
usage: "depth_stencil_attachment",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// VUID-VkImageViewCreateInfo-usage-02652
|
// VUID-VkImageViewCreateInfo-usage-02652
|
||||||
if usage.input_attachment
|
if usage.intersects(ImageUsage::INPUT_ATTACHMENT)
|
||||||
&& !(format_features.color_attachment || format_features.depth_stencil_attachment)
|
&& !format_features.intersects(
|
||||||
|
FormatFeatures::COLOR_ATTACHMENT | FormatFeatures::DEPTH_STENCIL_ATTACHMENT,
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return Err(ImageViewCreationError::FormatUsageNotSupported {
|
return Err(ImageViewCreationError::FormatUsageNotSupported {
|
||||||
usage: "input_attachment",
|
usage: "input_attachment",
|
||||||
@ -355,9 +363,11 @@ where
|
|||||||
|
|
||||||
if Some(format) != image_inner.format() {
|
if Some(format) != image_inner.format() {
|
||||||
// VUID-VkImageViewCreateInfo-image-01762
|
// VUID-VkImageViewCreateInfo-image-01762
|
||||||
if !image_inner.flags().mutable_format
|
if !image_inner
|
||||||
|
.flags()
|
||||||
|
.intersects(ImageCreateFlags::MUTABLE_FORMAT)
|
||||||
|| !image_inner.format().unwrap().planes().is_empty()
|
|| !image_inner.format().unwrap().planes().is_empty()
|
||||||
&& subresource_range.aspects.color
|
&& subresource_range.aspects.intersects(ImageAspects::COLOR)
|
||||||
{
|
{
|
||||||
return Err(ImageViewCreationError::FormatNotCompatible);
|
return Err(ImageViewCreationError::FormatNotCompatible);
|
||||||
}
|
}
|
||||||
@ -370,10 +380,9 @@ where
|
|||||||
&& format.components() != image_inner.format().unwrap().components()
|
&& format.components() != image_inner.format().unwrap().components()
|
||||||
{
|
{
|
||||||
return Err(ImageViewCreationError::RequirementNotMet {
|
return Err(ImageViewCreationError::RequirementNotMet {
|
||||||
required_for:
|
required_for: "this device is a portability subset device, and the format of \
|
||||||
"this device is a portability subset device, and the format of the image \
|
the image view does not have the same components and number of bits per \
|
||||||
view does not have the same components and number of bits per component as \
|
component as the parent image",
|
||||||
the parent image",
|
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["image_view_format_reinterpretation"],
|
features: &["image_view_format_reinterpretation"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -381,7 +390,10 @@ where
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if image_inner.flags().block_texel_view_compatible {
|
if image_inner
|
||||||
|
.flags()
|
||||||
|
.intersects(ImageCreateFlags::BLOCK_TEXEL_VIEW_COMPATIBLE)
|
||||||
|
{
|
||||||
// VUID-VkImageViewCreateInfo-image-01583
|
// VUID-VkImageViewCreateInfo-image-01583
|
||||||
if !(format.compatibility() == image_inner.format().unwrap().compatibility()
|
if !(format.compatibility() == image_inner.format().unwrap().compatibility()
|
||||||
|| format.block_size() == image_inner.format().unwrap().block_size())
|
|| format.block_size() == image_inner.format().unwrap().block_size())
|
||||||
@ -411,11 +423,11 @@ where
|
|||||||
return Err(ImageViewCreationError::FormatNotCompatible);
|
return Err(ImageViewCreationError::FormatNotCompatible);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let plane = if subresource_range.aspects.plane0 {
|
let plane = if subresource_range.aspects.intersects(ImageAspects::PLANE_0) {
|
||||||
0
|
0
|
||||||
} else if subresource_range.aspects.plane1 {
|
} else if subresource_range.aspects.intersects(ImageAspects::PLANE_1) {
|
||||||
1
|
1
|
||||||
} else if subresource_range.aspects.plane2 {
|
} else if subresource_range.aspects.intersects(ImageAspects::PLANE_2) {
|
||||||
2
|
2
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
@ -660,7 +672,7 @@ where
|
|||||||
format: image_inner.format(),
|
format: image_inner.format(),
|
||||||
image_type: image.dimensions().image_type(),
|
image_type: image.dimensions().image_type(),
|
||||||
tiling: image_inner.tiling(),
|
tiling: image_inner.tiling(),
|
||||||
usage: *image_inner.usage(),
|
usage: image_inner.usage(),
|
||||||
image_view_type: Some(view_type),
|
image_view_type: Some(view_type),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})?;
|
})?;
|
||||||
@ -689,19 +701,15 @@ where
|
|||||||
|
|
||||||
// https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VkImageViewCreateInfo.html#_description
|
// https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VkImageViewCreateInfo.html#_description
|
||||||
fn get_default_usage(aspects: ImageAspects, image: &Image) -> ImageUsage {
|
fn get_default_usage(aspects: ImageAspects, image: &Image) -> ImageUsage {
|
||||||
let has_stencil_aspect = aspects.stencil;
|
let has_stencil_aspect = aspects.intersects(ImageAspects::STENCIL);
|
||||||
let has_non_stencil_aspect = !(ImageAspects {
|
let has_non_stencil_aspect = !(aspects - ImageAspects::STENCIL).is_empty();
|
||||||
stencil: false,
|
|
||||||
..aspects
|
|
||||||
})
|
|
||||||
.is_empty();
|
|
||||||
|
|
||||||
if has_stencil_aspect && has_non_stencil_aspect {
|
if has_stencil_aspect && has_non_stencil_aspect {
|
||||||
*image.usage() & *image.stencil_usage()
|
image.usage() & image.stencil_usage()
|
||||||
} else if has_stencil_aspect {
|
} else if has_stencil_aspect {
|
||||||
*image.stencil_usage()
|
image.stencil_usage()
|
||||||
} else if has_non_stencil_aspect {
|
} else if has_non_stencil_aspect {
|
||||||
*image.usage()
|
image.usage()
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
@ -711,7 +719,7 @@ where
|
|||||||
unsafe fn get_format_features(format: Format, image: &Image) -> FormatFeatures {
|
unsafe fn get_format_features(format: Format, image: &Image) -> FormatFeatures {
|
||||||
let device = image.device();
|
let device = image.device();
|
||||||
|
|
||||||
let format_features = if Some(format) != image.format() {
|
let mut format_features = if Some(format) != image.format() {
|
||||||
// Use unchecked, because all validation should have been done before calling.
|
// Use unchecked, because all validation should have been done before calling.
|
||||||
let format_properties = device.physical_device().format_properties_unchecked(format);
|
let format_properties = device.physical_device().format_properties_unchecked(format);
|
||||||
|
|
||||||
@ -720,28 +728,34 @@ where
|
|||||||
ImageTiling::Linear => format_properties.linear_tiling_features,
|
ImageTiling::Linear => format_properties.linear_tiling_features,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
*image.format_features()
|
image.format_features()
|
||||||
};
|
};
|
||||||
|
|
||||||
if device.enabled_extensions().khr_format_feature_flags2 {
|
if !device.enabled_extensions().khr_format_feature_flags2 {
|
||||||
format_features
|
if format.type_color().is_none()
|
||||||
} else {
|
&& format_features.intersects(FormatFeatures::SAMPLED_IMAGE)
|
||||||
let is_without_format = format.shader_storage_image_without_format();
|
{
|
||||||
|
format_features |= FormatFeatures::SAMPLED_IMAGE_DEPTH_COMPARISON;
|
||||||
|
}
|
||||||
|
|
||||||
FormatFeatures {
|
if format.shader_storage_image_without_format() {
|
||||||
sampled_image_depth_comparison: format.type_color().is_none()
|
if device
|
||||||
&& format_features.sampled_image,
|
.enabled_features()
|
||||||
storage_read_without_format: is_without_format
|
.shader_storage_image_read_without_format
|
||||||
&& device
|
{
|
||||||
.enabled_features()
|
format_features |= FormatFeatures::STORAGE_READ_WITHOUT_FORMAT;
|
||||||
.shader_storage_image_read_without_format,
|
}
|
||||||
storage_write_without_format: is_without_format
|
|
||||||
&& device
|
if device
|
||||||
.enabled_features()
|
.enabled_features()
|
||||||
.shader_storage_image_write_without_format,
|
.shader_storage_image_write_without_format
|
||||||
..format_features
|
{
|
||||||
|
format_features |= FormatFeatures::STORAGE_WRITE_WITHOUT_FORMAT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
format_features
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the wrapped image that this image view was created from.
|
/// Returns the wrapped image that this image view was created from.
|
||||||
@ -1146,9 +1160,38 @@ impl From<RequirementNotMet> for ImageViewCreationError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vulkan_enum! {
|
vulkan_enum! {
|
||||||
/// The geometry type of an image view.
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
ImageViewType = ImageViewType(i32);
|
|
||||||
|
/// The geometry type of an image view.
|
||||||
|
ImageViewType impl {
|
||||||
|
/// Returns whether the type is arrayed.
|
||||||
|
#[inline]
|
||||||
|
pub fn is_arrayed(self) -> bool {
|
||||||
|
match self {
|
||||||
|
Self::Dim1d | Self::Dim2d | Self::Dim3d | Self::Cube => false,
|
||||||
|
Self::Dim1dArray | Self::Dim2dArray | Self::CubeArray => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns whether `self` is compatible with the given `image_type`.
|
||||||
|
#[inline]
|
||||||
|
pub fn is_compatible_with(self, image_type: ImageType) -> bool {
|
||||||
|
matches!(
|
||||||
|
(self, image_type,),
|
||||||
|
(
|
||||||
|
ImageViewType::Dim1d | ImageViewType::Dim1dArray,
|
||||||
|
ImageType::Dim1d
|
||||||
|
) | (
|
||||||
|
ImageViewType::Dim2d | ImageViewType::Dim2dArray,
|
||||||
|
ImageType::Dim2d | ImageType::Dim3d
|
||||||
|
) | (
|
||||||
|
ImageViewType::Cube | ImageViewType::CubeArray,
|
||||||
|
ImageType::Dim2d
|
||||||
|
) | (ImageViewType::Dim3d, ImageType::Dim3d)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
= ImageViewType(i32);
|
||||||
|
|
||||||
// TODO: document
|
// TODO: document
|
||||||
Dim1d = TYPE_1D,
|
Dim1d = TYPE_1D,
|
||||||
@ -1172,35 +1215,6 @@ vulkan_enum! {
|
|||||||
CubeArray = CUBE_ARRAY,
|
CubeArray = CUBE_ARRAY,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ImageViewType {
|
|
||||||
/// Returns whether the type is arrayed.
|
|
||||||
#[inline]
|
|
||||||
pub fn is_arrayed(&self) -> bool {
|
|
||||||
match self {
|
|
||||||
Self::Dim1d | Self::Dim2d | Self::Dim3d | Self::Cube => false,
|
|
||||||
Self::Dim1dArray | Self::Dim2dArray | Self::CubeArray => true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns whether `self` is compatible with the given `image_type`.
|
|
||||||
#[inline]
|
|
||||||
pub fn is_compatible_with(&self, image_type: ImageType) -> bool {
|
|
||||||
matches!(
|
|
||||||
(*self, image_type,),
|
|
||||||
(
|
|
||||||
ImageViewType::Dim1d | ImageViewType::Dim1dArray,
|
|
||||||
ImageType::Dim1d
|
|
||||||
) | (
|
|
||||||
ImageViewType::Dim2d | ImageViewType::Dim2dArray,
|
|
||||||
ImageType::Dim2d | ImageType::Dim3d
|
|
||||||
) | (
|
|
||||||
ImageViewType::Cube | ImageViewType::CubeArray,
|
|
||||||
ImageType::Dim2d
|
|
||||||
) | (ImageViewType::Dim3d, ImageType::Dim3d)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Trait for types that represent the GPU can access an image view.
|
/// Trait for types that represent the GPU can access an image view.
|
||||||
pub unsafe trait ImageViewAbstract:
|
pub unsafe trait ImageViewAbstract:
|
||||||
VulkanObject<Handle = ash::vk::ImageView> + DeviceOwned + Debug + Send + Sync
|
VulkanObject<Handle = ash::vk::ImageView> + DeviceOwned + Debug + Send + Sync
|
||||||
@ -1254,7 +1268,7 @@ pub unsafe trait ImageViewAbstract:
|
|||||||
fn format(&self) -> Option<Format>;
|
fn format(&self) -> Option<Format>;
|
||||||
|
|
||||||
/// Returns the features supported by the image view's format.
|
/// Returns the features supported by the image view's format.
|
||||||
fn format_features(&self) -> &FormatFeatures;
|
fn format_features(&self) -> FormatFeatures;
|
||||||
|
|
||||||
/// Returns the sampler YCbCr conversion that this image view was created with, if any.
|
/// Returns the sampler YCbCr conversion that this image view was created with, if any.
|
||||||
fn sampler_ycbcr_conversion(&self) -> Option<&Arc<SamplerYcbcrConversion>>;
|
fn sampler_ycbcr_conversion(&self) -> Option<&Arc<SamplerYcbcrConversion>>;
|
||||||
@ -1263,7 +1277,7 @@ pub unsafe trait ImageViewAbstract:
|
|||||||
fn subresource_range(&self) -> &ImageSubresourceRange;
|
fn subresource_range(&self) -> &ImageSubresourceRange;
|
||||||
|
|
||||||
/// Returns the usage of the image view.
|
/// Returns the usage of the image view.
|
||||||
fn usage(&self) -> &ImageUsage;
|
fn usage(&self) -> ImageUsage;
|
||||||
|
|
||||||
/// Returns the [`ImageViewType`] of this image view.
|
/// Returns the [`ImageViewType`] of this image view.
|
||||||
fn view_type(&self) -> ImageViewType;
|
fn view_type(&self) -> ImageViewType;
|
||||||
@ -1293,8 +1307,8 @@ where
|
|||||||
self.format
|
self.format
|
||||||
}
|
}
|
||||||
|
|
||||||
fn format_features(&self) -> &FormatFeatures {
|
fn format_features(&self) -> FormatFeatures {
|
||||||
&self.format_features
|
self.format_features
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sampler_ycbcr_conversion(&self) -> Option<&Arc<SamplerYcbcrConversion>> {
|
fn sampler_ycbcr_conversion(&self) -> Option<&Arc<SamplerYcbcrConversion>> {
|
||||||
@ -1305,8 +1319,8 @@ where
|
|||||||
&self.subresource_range
|
&self.subresource_range
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &ImageUsage {
|
fn usage(&self) -> ImageUsage {
|
||||||
&self.usage
|
self.usage
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view_type(&self) -> ImageViewType {
|
fn view_type(&self) -> ImageViewType {
|
||||||
@ -1341,8 +1355,8 @@ unsafe impl ImageViewAbstract for ImageView<dyn ImageAccess> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn format_features(&self) -> &FormatFeatures {
|
fn format_features(&self) -> FormatFeatures {
|
||||||
&self.format_features
|
self.format_features
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -1356,8 +1370,8 @@ unsafe impl ImageViewAbstract for ImageView<dyn ImageAccess> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn usage(&self) -> &ImageUsage {
|
fn usage(&self) -> ImageUsage {
|
||||||
&self.usage
|
self.usage
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -105,7 +105,7 @@ impl DebugUtilsMessenger {
|
|||||||
|
|
||||||
if !instance.enabled_extensions().ext_debug_utils {
|
if !instance.enabled_extensions().ext_debug_utils {
|
||||||
return Err(DebugUtilsMessengerCreationError::RequirementNotMet {
|
return Err(DebugUtilsMessengerCreationError::RequirementNotMet {
|
||||||
required_for: "`DebugUtilsMessenger`",
|
required_for: "`DebugUtilsMessenger::new`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
instance_extensions: &["ext_debug_utils"],
|
instance_extensions: &["ext_debug_utils"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -319,15 +319,8 @@ impl DebugUtilsMessengerCreateInfo {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn user_callback(user_callback: UserCallback) -> Self {
|
pub fn user_callback(user_callback: UserCallback) -> Self {
|
||||||
Self {
|
Self {
|
||||||
message_severity: DebugUtilsMessageSeverity {
|
message_severity: DebugUtilsMessageSeverity::ERROR | DebugUtilsMessageSeverity::WARNING,
|
||||||
error: true,
|
message_type: DebugUtilsMessageType::GENERAL,
|
||||||
warning: true,
|
|
||||||
..DebugUtilsMessageSeverity::empty()
|
|
||||||
},
|
|
||||||
message_type: DebugUtilsMessageType {
|
|
||||||
general: true,
|
|
||||||
..DebugUtilsMessageType::empty()
|
|
||||||
},
|
|
||||||
user_callback,
|
user_callback,
|
||||||
_ne: crate::NonExhaustive(()),
|
_ne: crate::NonExhaustive(()),
|
||||||
}
|
}
|
||||||
@ -363,36 +356,38 @@ pub struct Message<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vulkan_bitflags! {
|
vulkan_bitflags! {
|
||||||
/// Severity of message.
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
|
|
||||||
|
/// Severity of message.
|
||||||
DebugUtilsMessageSeverity = DebugUtilsMessageSeverityFlagsEXT(u32);
|
DebugUtilsMessageSeverity = DebugUtilsMessageSeverityFlagsEXT(u32);
|
||||||
|
|
||||||
/// An error that may cause undefined results, including an application crash.
|
/// An error that may cause undefined results, including an application crash.
|
||||||
error = ERROR,
|
ERROR = ERROR,
|
||||||
|
|
||||||
/// An unexpected use.
|
/// An unexpected use.
|
||||||
warning = WARNING,
|
WARNING = WARNING,
|
||||||
|
|
||||||
/// An informational message that may be handy when debugging an application.
|
/// An informational message that may be handy when debugging an application.
|
||||||
information = INFO,
|
INFO = INFO,
|
||||||
|
|
||||||
/// Diagnostic information from the loader and layers.
|
/// Diagnostic information from the loader and layers.
|
||||||
verbose = VERBOSE,
|
VERBOSE = VERBOSE,
|
||||||
}
|
}
|
||||||
|
|
||||||
vulkan_bitflags! {
|
vulkan_bitflags! {
|
||||||
/// Type of message.
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
|
|
||||||
|
/// Type of message.
|
||||||
DebugUtilsMessageType = DebugUtilsMessageTypeFlagsEXT(u32);
|
DebugUtilsMessageType = DebugUtilsMessageTypeFlagsEXT(u32);
|
||||||
|
|
||||||
/// Specifies that some general event has occurred.
|
/// Specifies that some general event has occurred.
|
||||||
general = GENERAL,
|
GENERAL = GENERAL,
|
||||||
|
|
||||||
/// Specifies that something has occurred during validation against the vulkan specification
|
/// Specifies that something has occurred during validation against the vulkan specification
|
||||||
validation = VALIDATION,
|
VALIDATION = VALIDATION,
|
||||||
|
|
||||||
/// Specifies a potentially non-optimal use of Vulkan
|
/// Specifies a potentially non-optimal use of Vulkan
|
||||||
performance = PERFORMANCE,
|
PERFORMANCE = PERFORMANCE,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A label to associate with a span of work in a queue.
|
/// A label to associate with a span of work in a queue.
|
||||||
@ -428,6 +423,8 @@ impl Default for DebugUtilsLabel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vulkan_enum! {
|
vulkan_enum! {
|
||||||
|
#[non_exhaustive]
|
||||||
|
|
||||||
/// Features of the validation layer to enable.
|
/// Features of the validation layer to enable.
|
||||||
ValidationFeatureEnable = ValidationFeatureEnableEXT(i32);
|
ValidationFeatureEnable = ValidationFeatureEnableEXT(i32);
|
||||||
|
|
||||||
@ -461,6 +458,8 @@ vulkan_enum! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vulkan_enum! {
|
vulkan_enum! {
|
||||||
|
#[non_exhaustive]
|
||||||
|
|
||||||
/// Features of the validation layer to disable.
|
/// Features of the validation layer to disable.
|
||||||
ValidationFeatureDisable = ValidationFeatureDisableEXT(i32);
|
ValidationFeatureDisable = ValidationFeatureDisableEXT(i32);
|
||||||
|
|
||||||
@ -529,16 +528,10 @@ mod tests {
|
|||||||
DebugUtilsMessenger::new(
|
DebugUtilsMessenger::new(
|
||||||
instance,
|
instance,
|
||||||
DebugUtilsMessengerCreateInfo {
|
DebugUtilsMessengerCreateInfo {
|
||||||
message_severity: DebugUtilsMessageSeverity {
|
message_severity: DebugUtilsMessageSeverity::ERROR,
|
||||||
error: true,
|
message_type: DebugUtilsMessageType::GENERAL
|
||||||
..DebugUtilsMessageSeverity::empty()
|
| DebugUtilsMessageType::VALIDATION
|
||||||
},
|
| DebugUtilsMessageType::PERFORMANCE,
|
||||||
message_type: DebugUtilsMessageType {
|
|
||||||
general: true,
|
|
||||||
validation: true,
|
|
||||||
performance: true,
|
|
||||||
..DebugUtilsMessageType::empty()
|
|
||||||
},
|
|
||||||
..DebugUtilsMessengerCreateInfo::user_callback(Arc::new(|_| {}))
|
..DebugUtilsMessengerCreateInfo::user_callback(Arc::new(|_| {}))
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -414,7 +414,8 @@ impl Instance {
|
|||||||
if !enabled_validation_features.is_empty() || !disabled_validation_features.is_empty() {
|
if !enabled_validation_features.is_empty() || !disabled_validation_features.is_empty() {
|
||||||
if !enabled_extensions.ext_validation_features {
|
if !enabled_extensions.ext_validation_features {
|
||||||
return Err(InstanceCreationError::RequirementNotMet {
|
return Err(InstanceCreationError::RequirementNotMet {
|
||||||
required_for: "`enabled_validation_features` or `disabled_validation_features` are not empty",
|
required_for: "`create_info.enabled_validation_features` or \
|
||||||
|
`create_info.disabled_validation_features` are not empty",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
instance_extensions: &["ext_validation_features"],
|
instance_extensions: &["ext_validation_features"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -464,7 +465,7 @@ impl Instance {
|
|||||||
// VUID-VkInstanceCreateInfo-pNext-04926
|
// VUID-VkInstanceCreateInfo-pNext-04926
|
||||||
if !enabled_extensions.ext_debug_utils {
|
if !enabled_extensions.ext_debug_utils {
|
||||||
return Err(InstanceCreationError::RequirementNotMet {
|
return Err(InstanceCreationError::RequirementNotMet {
|
||||||
required_for: "`debug_utils_messengers` is not empty",
|
required_for: "`create_info.debug_utils_messengers` is not empty",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
instance_extensions: &["ext_debug_utils"],
|
instance_extensions: &["ext_debug_utils"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -62,7 +62,11 @@
|
|||||||
//!
|
//!
|
||||||
|
|
||||||
//#![warn(missing_docs)] // TODO: activate
|
//#![warn(missing_docs)] // TODO: activate
|
||||||
#![warn(rust_2018_idioms, rust_2021_compatibility)]
|
#![warn(
|
||||||
|
rust_2018_idioms,
|
||||||
|
rust_2021_compatibility,
|
||||||
|
clippy::trivially_copy_pass_by_ref
|
||||||
|
)]
|
||||||
// These lints are a bit too pedantic, so they're disabled here.
|
// These lints are a bit too pedantic, so they're disabled here.
|
||||||
#![allow(
|
#![allow(
|
||||||
clippy::collapsible_else_if,
|
clippy::collapsible_else_if,
|
||||||
|
@ -10,7 +10,9 @@
|
|||||||
macro_rules! vulkan_bitflags {
|
macro_rules! vulkan_bitflags {
|
||||||
{
|
{
|
||||||
$(#[doc = $ty_doc:literal])*
|
$(#[doc = $ty_doc:literal])*
|
||||||
$ty:ident = $ty_ffi:ident($repr:ty);
|
$ty:ident
|
||||||
|
$( impl { $($impls:item)* } )?
|
||||||
|
= $ty_ffi:ident($repr:ty);
|
||||||
|
|
||||||
$(
|
$(
|
||||||
$(#[doc = $flag_doc:literal])*
|
$(#[doc = $flag_doc:literal])*
|
||||||
@ -18,23 +20,19 @@ macro_rules! vulkan_bitflags {
|
|||||||
)+
|
)+
|
||||||
} => {
|
} => {
|
||||||
$(#[doc = $ty_doc])*
|
$(#[doc = $ty_doc])*
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub struct $ty {
|
pub struct $ty($repr);
|
||||||
$(
|
|
||||||
$(#[doc = $flag_doc])*
|
|
||||||
pub $flag_name: bool,
|
|
||||||
)+
|
|
||||||
}
|
|
||||||
|
|
||||||
impl $ty {
|
impl $ty {
|
||||||
|
$(
|
||||||
|
$(#[doc = $flag_doc])*
|
||||||
|
pub const $flag_name: Self = Self(ash::vk::$ty_ffi::$flag_name_ffi.as_raw());
|
||||||
|
)*
|
||||||
|
|
||||||
#[doc = concat!("Returns a `", stringify!($ty), "` with none of the flags set.")]
|
#[doc = concat!("Returns a `", stringify!($ty), "` with none of the flags set.")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn empty() -> Self {
|
pub const fn empty() -> Self {
|
||||||
Self {
|
Self(0)
|
||||||
$(
|
|
||||||
$flag_name: false,
|
|
||||||
)+
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deprecated(since = "0.31.0", note = "Use `empty` instead.")]
|
#[deprecated(since = "0.31.0", note = "Use `empty` instead.")]
|
||||||
@ -47,120 +45,109 @@ macro_rules! vulkan_bitflags {
|
|||||||
#[doc = concat!("Returns a `", stringify!($ty), "` with all of the flags set.")]
|
#[doc = concat!("Returns a `", stringify!($ty), "` with all of the flags set.")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn all() -> Self {
|
pub const fn all() -> Self {
|
||||||
Self {
|
Self(Self::all_raw())
|
||||||
$(
|
}
|
||||||
$flag_name: true,
|
|
||||||
)+
|
const fn all_raw() -> $repr {
|
||||||
}
|
0
|
||||||
|
$(
|
||||||
|
| ash::vk::$ty_ffi::$flag_name_ffi.as_raw()
|
||||||
|
)*
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns whether no flags are set in `self`.
|
/// Returns whether no flags are set in `self`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn is_empty(&self) -> bool {
|
pub const fn is_empty(self) -> bool {
|
||||||
!(
|
self.0 == 0
|
||||||
$(
|
|
||||||
self.$flag_name
|
|
||||||
)||+
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns whether any flags are set in both `self` and `other`.
|
/// Returns whether any flags are set in both `self` and `other`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn intersects(&self, other: &Self) -> bool {
|
pub const fn intersects(self, #[allow(unused_variables)] other: Self) -> bool {
|
||||||
$(
|
self.0 & other.0 != 0
|
||||||
(self.$flag_name && other.$flag_name)
|
|
||||||
)||+
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns whether all flags in `other` are set in `self`.
|
/// Returns whether all flags in `other` are set in `self`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn contains(&self, other: &Self) -> bool {
|
pub const fn contains(self, #[allow(unused_variables)] other: Self) -> bool {
|
||||||
$(
|
self.0 & other.0 == other.0
|
||||||
(self.$flag_name || !other.$flag_name)
|
|
||||||
)&&+
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the union of `self` and `other`.
|
/// Returns the union of `self` and `other`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn union(&self, other: &Self) -> Self {
|
pub const fn union(self, #[allow(unused_variables)] other: Self) -> Self {
|
||||||
Self {
|
Self(self.0 | other.0)
|
||||||
$(
|
|
||||||
$flag_name: (self.$flag_name || other.$flag_name),
|
|
||||||
)+
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the intersection of `self` and `other`.
|
/// Returns the intersection of `self` and `other`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn intersection(&self, other: &Self) -> Self {
|
pub const fn intersection(self, #[allow(unused_variables)] other: Self) -> Self {
|
||||||
Self {
|
Self(self.0 & other.0)
|
||||||
$(
|
|
||||||
$flag_name: (self.$flag_name && other.$flag_name),
|
|
||||||
)+
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `self` without the flags set in `other`.
|
/// Returns `self` without the flags set in `other`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn difference(&self, other: &Self) -> Self {
|
pub const fn difference(self, #[allow(unused_variables)] other: Self) -> Self {
|
||||||
Self {
|
Self(self.0 & !other.0)
|
||||||
$(
|
|
||||||
$flag_name: (self.$flag_name && !other.$flag_name),
|
|
||||||
)+
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the flags set in `self` or `other`, but not both.
|
/// Returns the flags that are set in `self` or `other`, but not in both.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn symmetric_difference(&self, other: &Self) -> Self {
|
pub const fn symmetric_difference(self, #[allow(unused_variables)] other: Self) -> Self {
|
||||||
Self {
|
Self(self.0 ^ other.0)
|
||||||
$(
|
|
||||||
$flag_name: (self.$flag_name ^ other.$flag_name),
|
|
||||||
)+
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the flags not in `self`.
|
/// Returns the flags not in `self`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn complement(&self) -> Self {
|
pub const fn complement(self) -> Self {
|
||||||
Self {
|
Self(!self.0 & Self::all_raw())
|
||||||
$(
|
}
|
||||||
$flag_name: !self.$flag_name,
|
|
||||||
)+
|
$( $($impls)* )?
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for $ty {
|
||||||
|
#[inline]
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::empty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Debug for $ty {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
|
||||||
|
#[allow(unused_mut)]
|
||||||
|
let mut written = false;
|
||||||
|
|
||||||
|
$(
|
||||||
|
if self.intersects(Self::$flag_name) {
|
||||||
|
if written {
|
||||||
|
write!(f, " | ")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
write!(f, stringify!($flag_name))?;
|
||||||
|
written = true;
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
|
||||||
|
if !written {
|
||||||
|
write!(f, "empty()")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<$ty> for ash::vk::$ty_ffi {
|
impl From<$ty> for ash::vk::$ty_ffi {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(val: $ty) -> Self {
|
fn from(val: $ty) -> Self {
|
||||||
let mut result = ash::vk::$ty_ffi::empty();
|
ash::vk::$ty_ffi::from_raw(val.0)
|
||||||
$(
|
|
||||||
if val.$flag_name { result |= ash::vk::$ty_ffi::$flag_name_ffi }
|
|
||||||
)+
|
|
||||||
result
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ash::vk::$ty_ffi> for $ty {
|
impl From<ash::vk::$ty_ffi> for $ty {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(val: ash::vk::$ty_ffi) -> Self {
|
fn from(val: ash::vk::$ty_ffi) -> Self {
|
||||||
Self {
|
Self(val.as_raw() & Self::all_raw())
|
||||||
$(
|
|
||||||
$flag_name: val.intersects(ash::vk::$ty_ffi::$flag_name_ffi),
|
|
||||||
)+
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for $ty {
|
|
||||||
#[inline]
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
$(
|
|
||||||
$flag_name: false,
|
|
||||||
)+
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,14 +156,14 @@ macro_rules! vulkan_bitflags {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn bitand(self, rhs: Self) -> Self {
|
fn bitand(self, rhs: Self) -> Self {
|
||||||
self.intersection(&rhs)
|
self.intersection(rhs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::ops::BitAndAssign for $ty {
|
impl std::ops::BitAndAssign for $ty {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn bitand_assign(&mut self, rhs: Self) {
|
fn bitand_assign(&mut self, rhs: Self) {
|
||||||
*self = self.intersection(&rhs);
|
*self = self.intersection(rhs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,14 +172,14 @@ macro_rules! vulkan_bitflags {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn bitor(self, rhs: Self) -> Self {
|
fn bitor(self, rhs: Self) -> Self {
|
||||||
self.union(&rhs)
|
self.union(rhs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::ops::BitOrAssign for $ty {
|
impl std::ops::BitOrAssign for $ty {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn bitor_assign(&mut self, rhs: Self) {
|
fn bitor_assign(&mut self, rhs: Self) {
|
||||||
*self = self.union(&rhs);
|
*self = self.union(rhs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,14 +188,14 @@ macro_rules! vulkan_bitflags {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn bitxor(self, rhs: Self) -> Self {
|
fn bitxor(self, rhs: Self) -> Self {
|
||||||
self.symmetric_difference(&rhs)
|
self.symmetric_difference(rhs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::ops::BitXorAssign for $ty {
|
impl std::ops::BitXorAssign for $ty {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn bitxor_assign(&mut self, rhs: Self) {
|
fn bitxor_assign(&mut self, rhs: Self) {
|
||||||
*self = self.symmetric_difference(&rhs);
|
*self = self.symmetric_difference(rhs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,14 +204,14 @@ macro_rules! vulkan_bitflags {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn sub(self, rhs: Self) -> Self {
|
fn sub(self, rhs: Self) -> Self {
|
||||||
self.difference(&rhs)
|
self.difference(rhs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::ops::SubAssign for $ty {
|
impl std::ops::SubAssign for $ty {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn sub_assign(&mut self, rhs: Self) {
|
fn sub_assign(&mut self, rhs: Self) {
|
||||||
*self = self.difference(&rhs);
|
*self = self.difference(rhs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,9 +226,12 @@ macro_rules! vulkan_bitflags {
|
|||||||
};
|
};
|
||||||
|
|
||||||
{
|
{
|
||||||
$(#[doc = $ty_doc:literal])*
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
$ty:ident = $ty_ffi:ident($repr:ty);
|
|
||||||
|
$(#[doc = $ty_doc:literal])*
|
||||||
|
$ty:ident
|
||||||
|
$( impl { $($impls:item)* } )?
|
||||||
|
= $ty_ffi:ident($repr:ty);
|
||||||
|
|
||||||
$(
|
$(
|
||||||
$(#[doc = $flag_doc:literal])*
|
$(#[doc = $flag_doc:literal])*
|
||||||
@ -256,25 +246,19 @@ macro_rules! vulkan_bitflags {
|
|||||||
)*
|
)*
|
||||||
} => {
|
} => {
|
||||||
$(#[doc = $ty_doc])*
|
$(#[doc = $ty_doc])*
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub struct $ty {
|
pub struct $ty($repr);
|
||||||
$(
|
|
||||||
$(#[doc = $flag_doc])*
|
|
||||||
pub $flag_name: bool,
|
|
||||||
)*
|
|
||||||
pub _ne: crate::NonExhaustive,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl $ty {
|
impl $ty {
|
||||||
|
$(
|
||||||
|
$(#[doc = $flag_doc])*
|
||||||
|
pub const $flag_name: Self = Self(ash::vk::$ty_ffi::$flag_name_ffi.as_raw());
|
||||||
|
)*
|
||||||
|
|
||||||
#[doc = concat!("Returns a `", stringify!($ty), "` with none of the flags set.")]
|
#[doc = concat!("Returns a `", stringify!($ty), "` with none of the flags set.")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn empty() -> Self {
|
pub const fn empty() -> Self {
|
||||||
Self {
|
Self(0)
|
||||||
$(
|
|
||||||
$flag_name: false,
|
|
||||||
)*
|
|
||||||
_ne: crate::NonExhaustive(()),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deprecated(since = "0.31.0", note = "Use `empty` instead.")]
|
#[deprecated(since = "0.31.0", note = "Use `empty` instead.")]
|
||||||
@ -284,78 +268,59 @@ macro_rules! vulkan_bitflags {
|
|||||||
Self::empty()
|
Self::empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const fn all_raw() -> $repr {
|
||||||
|
0
|
||||||
|
$(
|
||||||
|
| ash::vk::$ty_ffi::$flag_name_ffi.as_raw()
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the number of flags set in self.
|
||||||
|
#[inline]
|
||||||
|
pub const fn count(self) -> u32 {
|
||||||
|
self.0.count_ones()
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns whether no flags are set in `self`.
|
/// Returns whether no flags are set in `self`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn is_empty(&self) -> bool {
|
pub const fn is_empty(self) -> bool {
|
||||||
!(
|
self.0 == 0
|
||||||
false
|
|
||||||
$(
|
|
||||||
|| self.$flag_name
|
|
||||||
)*
|
|
||||||
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns whether any flags are set in both `self` and `other`.
|
/// Returns whether any flags are set in both `self` and `other`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn intersects(&self, #[allow(unused_variables)] other: &Self) -> bool {
|
pub const fn intersects(self, #[allow(unused_variables)] other: Self) -> bool {
|
||||||
false
|
self.0 & other.0 != 0
|
||||||
$(
|
|
||||||
|| (self.$flag_name && other.$flag_name)
|
|
||||||
)*
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns whether all flags in `other` are set in `self`.
|
/// Returns whether all flags in `other` are set in `self`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn contains(&self, #[allow(unused_variables)] other: &Self) -> bool {
|
pub const fn contains(self, #[allow(unused_variables)] other: Self) -> bool {
|
||||||
true
|
self.0 & other.0 == other.0
|
||||||
$(
|
|
||||||
&& (self.$flag_name || !other.$flag_name)
|
|
||||||
)*
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the union of `self` and `other`.
|
/// Returns the union of `self` and `other`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn union(&self, #[allow(unused_variables)] other: &Self) -> Self {
|
pub const fn union(self, #[allow(unused_variables)] other: Self) -> Self {
|
||||||
Self {
|
Self(self.0 | other.0)
|
||||||
$(
|
|
||||||
$flag_name: (self.$flag_name || other.$flag_name),
|
|
||||||
)*
|
|
||||||
_ne: crate::NonExhaustive(()),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the intersection of `self` and `other`.
|
/// Returns the intersection of `self` and `other`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn intersection(&self, #[allow(unused_variables)] other: &Self) -> Self {
|
pub const fn intersection(self, #[allow(unused_variables)] other: Self) -> Self {
|
||||||
Self {
|
Self(self.0 & other.0)
|
||||||
$(
|
|
||||||
$flag_name: (self.$flag_name && other.$flag_name),
|
|
||||||
)*
|
|
||||||
_ne: crate::NonExhaustive(()),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `self` without the flags set in `other`.
|
/// Returns `self` without the flags set in `other`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn difference(&self, #[allow(unused_variables)] other: &Self) -> Self {
|
pub const fn difference(self, #[allow(unused_variables)] other: Self) -> Self {
|
||||||
Self {
|
Self(self.0 & !other.0)
|
||||||
$(
|
|
||||||
$flag_name: (self.$flag_name ^ other.$flag_name),
|
|
||||||
)*
|
|
||||||
_ne: crate::NonExhaustive(()),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the flags set in `self` or `other`, but not both.
|
/// Returns the flags that are set in `self` or `other`, but not in both.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn symmetric_difference(&self, #[allow(unused_variables)] other: &Self) -> Self {
|
pub const fn symmetric_difference(self, #[allow(unused_variables)] other: Self) -> Self {
|
||||||
Self {
|
Self(self.0 ^ other.0)
|
||||||
$(
|
|
||||||
$flag_name: (self.$flag_name ^ other.$flag_name),
|
|
||||||
)*
|
|
||||||
_ne: crate::NonExhaustive(()),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@ -365,7 +330,7 @@ macro_rules! vulkan_bitflags {
|
|||||||
) -> Result<(), crate::RequirementNotMet> {
|
) -> Result<(), crate::RequirementNotMet> {
|
||||||
$(
|
$(
|
||||||
$(
|
$(
|
||||||
if self.$flag_name && ![
|
if self.intersects(Self::$flag_name) && ![
|
||||||
$(
|
$(
|
||||||
device.api_version() >= crate::Version::$api_version,
|
device.api_version() >= crate::Version::$api_version,
|
||||||
)?
|
)?
|
||||||
@ -403,7 +368,7 @@ macro_rules! vulkan_bitflags {
|
|||||||
) -> Result<(), crate::RequirementNotMet> {
|
) -> Result<(), crate::RequirementNotMet> {
|
||||||
$(
|
$(
|
||||||
$(
|
$(
|
||||||
if self.$flag_name && ![
|
if self.intersects(Self::$flag_name) && ![
|
||||||
$(
|
$(
|
||||||
physical_device.api_version() >= crate::Version::$api_version,
|
physical_device.api_version() >= crate::Version::$api_version,
|
||||||
)?
|
)?
|
||||||
@ -441,7 +406,7 @@ macro_rules! vulkan_bitflags {
|
|||||||
) -> Result<(), crate::RequirementNotMet> {
|
) -> Result<(), crate::RequirementNotMet> {
|
||||||
$(
|
$(
|
||||||
$(
|
$(
|
||||||
if self.$flag_name && ![
|
if self.intersects(Self::$flag_name) && ![
|
||||||
$(
|
$(
|
||||||
instance.api_version() >= crate::Version::$api_version,
|
instance.api_version() >= crate::Version::$api_version,
|
||||||
)?
|
)?
|
||||||
@ -463,41 +428,52 @@ macro_rules! vulkan_bitflags {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl From<$ty> for ash::vk::$ty_ffi {
|
$( $($impls)* )?
|
||||||
#[inline]
|
|
||||||
fn from(#[allow(unused_variables)] val: $ty) -> Self {
|
|
||||||
#[allow(unused_mut)]
|
|
||||||
let mut result = ash::vk::$ty_ffi::empty();
|
|
||||||
$(
|
|
||||||
if val.$flag_name { result |= ash::vk::$ty_ffi::$flag_name_ffi }
|
|
||||||
)*
|
|
||||||
result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<ash::vk::$ty_ffi> for $ty {
|
|
||||||
#[inline]
|
|
||||||
fn from(#[allow(unused_variables)] val: ash::vk::$ty_ffi) -> Self {
|
|
||||||
Self {
|
|
||||||
$(
|
|
||||||
$flag_name: val.intersects(ash::vk::$ty_ffi::$flag_name_ffi),
|
|
||||||
)*
|
|
||||||
_ne: crate::NonExhaustive(()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for $ty {
|
impl Default for $ty {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self::empty()
|
||||||
$(
|
}
|
||||||
$flag_name: false,
|
}
|
||||||
)*
|
|
||||||
_ne: crate::NonExhaustive(()),
|
impl std::fmt::Debug for $ty {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
|
||||||
|
#[allow(unused_mut)]
|
||||||
|
let mut written = false;
|
||||||
|
|
||||||
|
$(
|
||||||
|
if self.intersects(Self::$flag_name) {
|
||||||
|
if written {
|
||||||
|
write!(f, " | ")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
write!(f, stringify!($flag_name))?;
|
||||||
|
written = true;
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
|
||||||
|
if !written {
|
||||||
|
write!(f, "empty()")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<$ty> for ash::vk::$ty_ffi {
|
||||||
|
#[inline]
|
||||||
|
fn from(val: $ty) -> Self {
|
||||||
|
ash::vk::$ty_ffi::from_raw(val.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ash::vk::$ty_ffi> for $ty {
|
||||||
|
#[inline]
|
||||||
|
fn from(val: ash::vk::$ty_ffi) -> Self {
|
||||||
|
Self(val.as_raw() & Self::all_raw())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -506,14 +482,14 @@ macro_rules! vulkan_bitflags {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn bitand(self, rhs: Self) -> Self {
|
fn bitand(self, rhs: Self) -> Self {
|
||||||
self.intersection(&rhs)
|
self.intersection(rhs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::ops::BitAndAssign for $ty {
|
impl std::ops::BitAndAssign for $ty {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn bitand_assign(&mut self, rhs: Self) {
|
fn bitand_assign(&mut self, rhs: Self) {
|
||||||
*self = self.intersection(&rhs);
|
*self = self.intersection(rhs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -522,14 +498,14 @@ macro_rules! vulkan_bitflags {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn bitor(self, rhs: Self) -> Self {
|
fn bitor(self, rhs: Self) -> Self {
|
||||||
self.union(&rhs)
|
self.union(rhs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::ops::BitOrAssign for $ty {
|
impl std::ops::BitOrAssign for $ty {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn bitor_assign(&mut self, rhs: Self) {
|
fn bitor_assign(&mut self, rhs: Self) {
|
||||||
*self = self.union(&rhs);
|
*self = self.union(rhs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -538,14 +514,14 @@ macro_rules! vulkan_bitflags {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn bitxor(self, rhs: Self) -> Self {
|
fn bitxor(self, rhs: Self) -> Self {
|
||||||
self.symmetric_difference(&rhs)
|
self.symmetric_difference(rhs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::ops::BitXorAssign for $ty {
|
impl std::ops::BitXorAssign for $ty {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn bitxor_assign(&mut self, rhs: Self) {
|
fn bitxor_assign(&mut self, rhs: Self) {
|
||||||
*self = self.symmetric_difference(&rhs);
|
*self = self.symmetric_difference(rhs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -554,14 +530,14 @@ macro_rules! vulkan_bitflags {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn sub(self, rhs: Self) -> Self {
|
fn sub(self, rhs: Self) -> Self {
|
||||||
self.difference(&rhs)
|
self.difference(rhs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::ops::SubAssign for $ty {
|
impl std::ops::SubAssign for $ty {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn sub_assign(&mut self, rhs: Self) {
|
fn sub_assign(&mut self, rhs: Self) {
|
||||||
*self = self.difference(&rhs);
|
*self = self.difference(rhs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -570,7 +546,9 @@ macro_rules! vulkan_bitflags {
|
|||||||
macro_rules! vulkan_enum {
|
macro_rules! vulkan_enum {
|
||||||
{
|
{
|
||||||
$(#[doc = $ty_doc:literal])*
|
$(#[doc = $ty_doc:literal])*
|
||||||
$ty:ident = $ty_ffi:ident($repr:ty);
|
$ty:ident
|
||||||
|
$( impl { $($impls:item)* } )?
|
||||||
|
= $ty_ffi:ident($repr:ty);
|
||||||
|
|
||||||
$(
|
$(
|
||||||
$(#[doc = $flag_doc:literal])*
|
$(#[doc = $flag_doc:literal])*
|
||||||
@ -587,6 +565,12 @@ macro_rules! vulkan_enum {
|
|||||||
)+
|
)+
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$(
|
||||||
|
impl $ty {
|
||||||
|
$($impls)*
|
||||||
|
}
|
||||||
|
)?
|
||||||
|
|
||||||
impl From<$ty> for ash::vk::$ty_ffi {
|
impl From<$ty> for ash::vk::$ty_ffi {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(val: $ty) -> Self {
|
fn from(val: $ty) -> Self {
|
||||||
@ -610,9 +594,12 @@ macro_rules! vulkan_enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
{
|
{
|
||||||
$(#[doc = $ty_doc:literal])*
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
$ty:ident = $ty_ffi:ident($repr:ty);
|
|
||||||
|
$(#[doc = $ty_doc:literal])*
|
||||||
|
$ty:ident
|
||||||
|
$( impl { $($impls:item)* } )?
|
||||||
|
= $ty_ffi:ident($repr:ty);
|
||||||
|
|
||||||
$(
|
$(
|
||||||
$(#[doc = $flag_doc:literal])*
|
$(#[doc = $flag_doc:literal])*
|
||||||
@ -758,6 +745,10 @@ macro_rules! vulkan_enum {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$(
|
||||||
|
$($impls)*
|
||||||
|
)?
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<$ty> for ash::vk::$ty_ffi {
|
impl From<$ty> for ash::vk::$ty_ffi {
|
||||||
@ -783,4 +774,118 @@ macro_rules! vulkan_enum {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) use {vulkan_bitflags, vulkan_enum};
|
macro_rules! vulkan_bitflags_enum {
|
||||||
|
{
|
||||||
|
#[non_exhaustive]
|
||||||
|
|
||||||
|
$(#[doc = $ty_bitflags_doc:literal])*
|
||||||
|
$ty_bitflags:ident
|
||||||
|
$( impl { $($impls_bitflags:item)* } )?
|
||||||
|
,
|
||||||
|
|
||||||
|
$(#[doc = $ty_enum_doc:literal])*
|
||||||
|
$ty_enum:ident
|
||||||
|
$( impl { $($impls_enum:item)* } )?
|
||||||
|
,
|
||||||
|
|
||||||
|
= $ty_ffi:ident($repr:ty);
|
||||||
|
|
||||||
|
$(
|
||||||
|
$(#[doc = $flag_doc:literal])*
|
||||||
|
$flag_name_bitflags:ident, $flag_name_enum:ident = $flag_name_ffi:ident
|
||||||
|
$({
|
||||||
|
$(api_version: $api_version:ident,)?
|
||||||
|
$(features: [$($feature:ident),+ $(,)?],)?
|
||||||
|
$(device_extensions: [$($device_extension:ident),+ $(,)?],)?
|
||||||
|
$(instance_extensions: [$($instance_extension:ident),+ $(,)?],)?
|
||||||
|
})?
|
||||||
|
,
|
||||||
|
)*
|
||||||
|
} => {
|
||||||
|
crate::macros::vulkan_bitflags! {
|
||||||
|
#[non_exhaustive]
|
||||||
|
|
||||||
|
$(#[doc = $ty_bitflags_doc])*
|
||||||
|
$ty_bitflags
|
||||||
|
impl {
|
||||||
|
/// Returns whether `self` contains the flag corresponding to `val`.
|
||||||
|
#[inline]
|
||||||
|
pub fn contains_enum(self, val: $ty_enum) -> bool {
|
||||||
|
self.intersects(val.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
$( $($impls_bitflags)* )?
|
||||||
|
}
|
||||||
|
= $ty_ffi($repr);
|
||||||
|
|
||||||
|
$(
|
||||||
|
$(#[doc = $flag_doc])*
|
||||||
|
$flag_name_bitflags = $flag_name_ffi
|
||||||
|
$({
|
||||||
|
$(api_version: $api_version,)?
|
||||||
|
$(features: [$($feature),+],)?
|
||||||
|
$(device_extensions: [$($device_extension),+],)?
|
||||||
|
$(instance_extensions: [$($instance_extension),+],)?
|
||||||
|
})?
|
||||||
|
,
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
|
||||||
|
crate::macros::vulkan_enum! {
|
||||||
|
#[non_exhaustive]
|
||||||
|
|
||||||
|
$(#[doc = $ty_enum_doc])*
|
||||||
|
$ty_enum
|
||||||
|
$( impl { $($impls_enum)* } )?
|
||||||
|
= $ty_ffi($repr);
|
||||||
|
|
||||||
|
$(
|
||||||
|
$(#[doc = $flag_doc])*
|
||||||
|
$flag_name_enum = $flag_name_ffi
|
||||||
|
$({
|
||||||
|
$(api_version: $api_version,)?
|
||||||
|
$(features: [$($feature),+],)?
|
||||||
|
$(device_extensions: [$($device_extension),+],)?
|
||||||
|
$(instance_extensions: [$($instance_extension),+],)?
|
||||||
|
})?
|
||||||
|
,
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<$ty_enum> for $ty_bitflags {
|
||||||
|
#[inline]
|
||||||
|
fn from(val: $ty_enum) -> Self {
|
||||||
|
Self(val as $repr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromIterator<$ty_enum> for $ty_bitflags {
|
||||||
|
#[inline]
|
||||||
|
fn from_iter<T>(iter: T) -> Self where T: IntoIterator<Item = $ty_enum> {
|
||||||
|
iter.into_iter().map(|item| Self::from(item)).fold(Self::empty(), |r, i| r.union(i))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoIterator for $ty_bitflags {
|
||||||
|
type Item = $ty_enum;
|
||||||
|
type IntoIter = std::iter::Flatten<
|
||||||
|
std::array::IntoIter<
|
||||||
|
Option<Self::Item>,
|
||||||
|
{ $ty_bitflags::all_raw().count_ones() as usize },
|
||||||
|
>
|
||||||
|
>;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
[
|
||||||
|
$(
|
||||||
|
self.intersects(Self::$flag_name_bitflags)
|
||||||
|
.then_some($ty_enum::$flag_name_enum),
|
||||||
|
)*
|
||||||
|
].into_iter().flatten()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) use {vulkan_bitflags, vulkan_bitflags_enum, vulkan_enum};
|
||||||
|
@ -353,17 +353,17 @@ impl From<MemoryUsage> for MemoryTypeFilter {
|
|||||||
|
|
||||||
match usage {
|
match usage {
|
||||||
MemoryUsage::GpuOnly => {
|
MemoryUsage::GpuOnly => {
|
||||||
filter.preferred_flags.device_local = true;
|
filter.preferred_flags |= MemoryPropertyFlags::DEVICE_LOCAL;
|
||||||
filter.not_preferred_flags.host_visible = true;
|
filter.not_preferred_flags |= MemoryPropertyFlags::HOST_VISIBLE;
|
||||||
}
|
}
|
||||||
MemoryUsage::Upload => {
|
MemoryUsage::Upload => {
|
||||||
filter.required_flags.host_visible = true;
|
filter.required_flags |= MemoryPropertyFlags::HOST_VISIBLE;
|
||||||
filter.preferred_flags.device_local = true;
|
filter.preferred_flags |= MemoryPropertyFlags::DEVICE_LOCAL;
|
||||||
filter.not_preferred_flags.host_cached = true;
|
filter.not_preferred_flags |= MemoryPropertyFlags::HOST_CACHED;
|
||||||
}
|
}
|
||||||
MemoryUsage::Download => {
|
MemoryUsage::Download => {
|
||||||
filter.required_flags.host_visible = true;
|
filter.required_flags |= MemoryPropertyFlags::HOST_VISIBLE;
|
||||||
filter.preferred_flags.host_cached = true;
|
filter.preferred_flags |= MemoryPropertyFlags::HOST_CACHED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -464,8 +464,8 @@ impl Default for AllocationCreateInfo<'_> {
|
|||||||
pub enum MemoryUsage {
|
pub enum MemoryUsage {
|
||||||
/// The memory is intended to only be used by the GPU.
|
/// The memory is intended to only be used by the GPU.
|
||||||
///
|
///
|
||||||
/// Prefers picking a memory type with the [`device_local`] flag and without the
|
/// Prefers picking a memory type with the [`DEVICE_LOCAL`] flag and
|
||||||
/// [`host_visible`] flag.
|
/// without the [`HOST_VISIBLE`] flag.
|
||||||
///
|
///
|
||||||
/// This option is what you will always want to use unless the memory needs to be accessed by
|
/// This option is what you will always want to use unless the memory needs to be accessed by
|
||||||
/// the CPU, because a memory type that can only be accessed by the GPU is going to give the
|
/// the CPU, because a memory type that can only be accessed by the GPU is going to give the
|
||||||
@ -473,37 +473,37 @@ pub enum MemoryUsage {
|
|||||||
/// once and then never again, or resources that are only written and read by the GPU, like
|
/// once and then never again, or resources that are only written and read by the GPU, like
|
||||||
/// render targets and intermediary buffers.
|
/// render targets and intermediary buffers.
|
||||||
///
|
///
|
||||||
/// [`device_local`]: MemoryPropertyFlags::device_local
|
/// [`DEVICE_LOCAL`]: MemoryPropertyFlags::DEVICE_LOCAL
|
||||||
/// [`host_visible`]: MemoryPropertyFlags::host_visible
|
/// [`HOST_VISIBLE`]: MemoryPropertyFlags::HOST_VISIBLE
|
||||||
GpuOnly,
|
GpuOnly,
|
||||||
|
|
||||||
/// The memory is intended for upload to the GPU.
|
/// The memory is intended for upload to the GPU.
|
||||||
///
|
///
|
||||||
/// Guarantees picking a memory type with the [`host_visible`] flag. Prefers picking one
|
/// Guarantees picking a memory type with the [`HOST_VISIBLE`] flag. Prefers picking one
|
||||||
/// without the [`host_cached`] flag and with the [`device_local`] flag.
|
/// without the [`HOST_CACHED`] flag and with the [`DEVICE_LOCAL`] flag.
|
||||||
///
|
///
|
||||||
/// This option is best suited for resources that need to be constantly updated by the CPU,
|
/// This option is best suited for resources that need to be constantly updated by the CPU,
|
||||||
/// like vertex and index buffers for example. It is also neccessary for *staging buffers*,
|
/// like vertex and index buffers for example. It is also neccessary for *staging buffers*,
|
||||||
/// whose only purpose in life it is to get data into `device_local` memory or texels into an
|
/// whose only purpose in life it is to get data into `device_local` memory or texels into an
|
||||||
/// optimal image.
|
/// optimal image.
|
||||||
///
|
///
|
||||||
/// [`host_visible`]: MemoryPropertyFlags::host_visible
|
/// [`HOST_VISIBLE`]: MemoryPropertyFlags::HOST_VISIBLE
|
||||||
/// [`host_cached`]: MemoryPropertyFlags::host_cached
|
/// [`HOST_CACHED`]: MemoryPropertyFlags::HOST_CACHED
|
||||||
/// [`device_local`]: MemoryPropertyFlags::device_local
|
/// [`DEVICE_LOCAL`]: MemoryPropertyFlags::DEVICE_LOCAL
|
||||||
Upload,
|
Upload,
|
||||||
|
|
||||||
/// The memory is intended for download from the GPU.
|
/// The memory is intended for download from the GPU.
|
||||||
///
|
///
|
||||||
/// Guarantees picking a memory type with the [`host_visible`] flag. Prefers picking one with
|
/// Guarantees picking a memory type with the [`HOST_VISIBLE`] flag. Prefers picking one with
|
||||||
/// the [`host_cached`] flag and without the [`device_local`] flag.
|
/// the [`HOST_CACHED`] flag and without the [`DEVICE_LOCAL`] flag.
|
||||||
///
|
///
|
||||||
/// This option is best suited if you're using the GPU for things other than rendering and you
|
/// This option is best suited if you're using the GPU for things other than rendering and you
|
||||||
/// need to get the results back to the CPU. That might be compute shading, or image or video
|
/// need to get the results back to the CPU. That might be compute shading, or image or video
|
||||||
/// manipulation, or screenshotting for example.
|
/// manipulation, or screenshotting for example.
|
||||||
///
|
///
|
||||||
/// [`host_visible`]: MemoryPropertyFlags::host_visible
|
/// [`HOST_VISIBLE`]: MemoryPropertyFlags::HOST_VISIBLE
|
||||||
/// [`host_cached`]: MemoryPropertyFlags::host_cached
|
/// [`HOST_CACHED`]: MemoryPropertyFlags::HOST_CACHED
|
||||||
/// [`device_local`]: MemoryPropertyFlags::device_local
|
/// [`DEVICE_LOCAL`]: MemoryPropertyFlags::DEVICE_LOCAL
|
||||||
Download,
|
Download,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -762,7 +762,7 @@ impl<S: Suballocator> GenericMemoryAllocator<S> {
|
|||||||
&& device.enabled_extensions().khr_external_memory)
|
&& device.enabled_extensions().khr_external_memory)
|
||||||
{
|
{
|
||||||
return Err(GenericMemoryAllocatorCreationError::RequirementNotMet {
|
return Err(GenericMemoryAllocatorCreationError::RequirementNotMet {
|
||||||
required_for: "`create_info.export_handle_types` was not empty",
|
required_for: "`create_info.export_handle_types` is not empty",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
api_version: Some(Version::V1_1),
|
api_version: Some(Version::V1_1),
|
||||||
device_extensions: &["khr_external_memory"],
|
device_extensions: &["khr_external_memory"],
|
||||||
@ -853,12 +853,13 @@ impl<S: Suballocator> GenericMemoryAllocator<S> {
|
|||||||
|
|
||||||
let mut memory_type_bits = u32::MAX;
|
let mut memory_type_bits = u32::MAX;
|
||||||
for (index, MemoryType { property_flags, .. }) in memory_types.iter().enumerate() {
|
for (index, MemoryType { property_flags, .. }) in memory_types.iter().enumerate() {
|
||||||
if property_flags.lazily_allocated
|
if property_flags.intersects(
|
||||||
|| property_flags.protected
|
MemoryPropertyFlags::LAZILY_ALLOCATED
|
||||||
|| property_flags.device_coherent
|
| MemoryPropertyFlags::PROTECTED
|
||||||
|| property_flags.device_uncached
|
| MemoryPropertyFlags::DEVICE_COHERENT
|
||||||
|| property_flags.rdma_capable
|
| MemoryPropertyFlags::DEVICE_UNCACHED
|
||||||
{
|
| MemoryPropertyFlags::RDMA_CAPABLE,
|
||||||
|
) {
|
||||||
// VUID-VkMemoryAllocateInfo-memoryTypeIndex-01872
|
// VUID-VkMemoryAllocateInfo-memoryTypeIndex-01872
|
||||||
// VUID-vkAllocateMemory-deviceCoherentMemory-02790
|
// VUID-vkAllocateMemory-deviceCoherentMemory-02790
|
||||||
// Lazily allocated memory would just cause problems for suballocation in general.
|
// Lazily allocated memory would just cause problems for suballocation in general.
|
||||||
@ -879,9 +880,10 @@ impl<S: Suballocator> GenericMemoryAllocator<S> {
|
|||||||
allocation_type,
|
allocation_type,
|
||||||
dedicated_allocation,
|
dedicated_allocation,
|
||||||
export_handle_types,
|
export_handle_types,
|
||||||
flags: MemoryAllocateFlags {
|
flags: if device_address {
|
||||||
device_address,
|
MemoryAllocateFlags::DEVICE_ADDRESS
|
||||||
..Default::default()
|
} else {
|
||||||
|
MemoryAllocateFlags::empty()
|
||||||
},
|
},
|
||||||
memory_type_bits,
|
memory_type_bits,
|
||||||
max_allocations,
|
max_allocations,
|
||||||
@ -994,9 +996,9 @@ unsafe impl<S: Suballocator> MemoryAllocator for GenericMemoryAllocator<S> {
|
|||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// - Panics if `memory_type_index` is not less than the number of available memory types.
|
/// - Panics if `memory_type_index` is not less than the number of available memory types.
|
||||||
/// - Panics if `memory_type_index` refers to a memory type which has the [`protected`] flag set
|
/// - Panics if `memory_type_index` refers to a memory type which has the [`PROTECTED`] flag set
|
||||||
/// and the [`protected_memory`] feature is not enabled on the device.
|
/// and the [`protected_memory`] feature is not enabled on the device.
|
||||||
/// - Panics if `memory_type_index` refers to a memory type which has the [`device_coherent`]
|
/// - Panics if `memory_type_index` refers to a memory type which has the [`DEVICE_COHERENT`]
|
||||||
/// flag set and the [`device_coherent_memory`] feature is not enabled on the device.
|
/// flag set and the [`device_coherent_memory`] feature is not enabled on the device.
|
||||||
/// - Panics if `create_info.size` is zero.
|
/// - Panics if `create_info.size` is zero.
|
||||||
/// - Panics if `create_info.alignment` is zero.
|
/// - Panics if `create_info.alignment` is zero.
|
||||||
@ -1012,9 +1014,9 @@ unsafe impl<S: Suballocator> MemoryAllocator for GenericMemoryAllocator<S> {
|
|||||||
/// - Returns [`SuballocatorBlockSizeExceeded`] if `S` is `PoolAllocator<BLOCK_SIZE>` and
|
/// - Returns [`SuballocatorBlockSizeExceeded`] if `S` is `PoolAllocator<BLOCK_SIZE>` and
|
||||||
/// `create_info.size` is greater than `BLOCK_SIZE`.
|
/// `create_info.size` is greater than `BLOCK_SIZE`.
|
||||||
///
|
///
|
||||||
/// [`protected`]: MemoryPropertyFlags::protected
|
/// [`PROTECTED`]: MemoryPropertyFlags::PROTECTED
|
||||||
/// [`protected_memory`]: crate::device::Features::protected_memory
|
/// [`protected_memory`]: crate::device::Features::protected_memory
|
||||||
/// [`device_coherent`]: MemoryPropertyFlags::device_coherent
|
/// [`DEVICE_COHERENT`]: MemoryPropertyFlags::DEVICE_COHERENT
|
||||||
/// [`device_coherent_memory`]: crate::device::Features::device_coherent_memory
|
/// [`device_coherent_memory`]: crate::device::Features::device_coherent_memory
|
||||||
/// [`TooManyObjects`]: VulkanError::TooManyObjects
|
/// [`TooManyObjects`]: VulkanError::TooManyObjects
|
||||||
/// [`BlockSizeExceeded`]: AllocationCreationError::BlockSizeExceeded
|
/// [`BlockSizeExceeded`]: AllocationCreationError::BlockSizeExceeded
|
||||||
@ -1235,13 +1237,11 @@ unsafe impl<S: Suballocator> MemoryAllocator for GenericMemoryAllocator<S> {
|
|||||||
/// `create_info.size` is greater than `BLOCK_SIZE` and a dedicated allocation was not
|
/// `create_info.size` is greater than `BLOCK_SIZE` and a dedicated allocation was not
|
||||||
/// created.
|
/// created.
|
||||||
///
|
///
|
||||||
/// [`device_local`]: MemoryPropertyFlags::device_local
|
|
||||||
/// [`host_visible`]: MemoryPropertyFlags::host_visible
|
|
||||||
/// [`TooManyObjects`]: VulkanError::TooManyObjects
|
/// [`TooManyObjects`]: VulkanError::TooManyObjects
|
||||||
/// [`SuballocatorBlockSizeExceeded`]: AllocationCreationError::SuballocatorBlockSizeExceeded
|
|
||||||
/// [`OutOfPoolMemory`]: AllocationCreationError::OutOfPoolMemory
|
/// [`OutOfPoolMemory`]: AllocationCreationError::OutOfPoolMemory
|
||||||
/// [`DedicatedAllocationRequired`]: AllocationCreationError::DedicatedAllocationRequired
|
/// [`DedicatedAllocationRequired`]: AllocationCreationError::DedicatedAllocationRequired
|
||||||
/// [`BlockSizeExceeded`]: AllocationCreationError::BlockSizeExceeded
|
/// [`BlockSizeExceeded`]: AllocationCreationError::BlockSizeExceeded
|
||||||
|
/// [`SuballocatorBlockSizeExceeded`]: AllocationCreationError::SuballocatorBlockSizeExceeded
|
||||||
fn allocate(
|
fn allocate(
|
||||||
&self,
|
&self,
|
||||||
create_info: AllocationCreateInfo<'_>,
|
create_info: AllocationCreateInfo<'_>,
|
||||||
@ -1549,10 +1549,10 @@ pub struct GenericMemoryAllocatorCreateInfo<'b, 'e> {
|
|||||||
pub export_handle_types: &'e [ExternalMemoryHandleTypes],
|
pub export_handle_types: &'e [ExternalMemoryHandleTypes],
|
||||||
|
|
||||||
/// Whether the allocator should allocate the [`DeviceMemory`] blocks with the
|
/// Whether the allocator should allocate the [`DeviceMemory`] blocks with the
|
||||||
/// [`device_address`] flag set.
|
/// [`DEVICE_ADDRESS`] flag set.
|
||||||
///
|
///
|
||||||
/// This is required if you want to allocate memory for buffers that have the
|
/// This is required if you want to allocate memory for buffers that have the
|
||||||
/// [`shader_device_address`] usage set. For this option too, there is no reason to disable it.
|
/// [`SHADER_DEVICE_ADDRESS`] usage set. For this option too, there is no reason to disable it.
|
||||||
///
|
///
|
||||||
/// This option is silently ignored (treated as `false`) if the [`buffer_device_address`]
|
/// This option is silently ignored (treated as `false`) if the [`buffer_device_address`]
|
||||||
/// feature is not enabled on the device or if the [`ext_buffer_device_address`] extension is
|
/// feature is not enabled on the device or if the [`ext_buffer_device_address`] extension is
|
||||||
@ -1561,8 +1561,8 @@ pub struct GenericMemoryAllocatorCreateInfo<'b, 'e> {
|
|||||||
///
|
///
|
||||||
/// The default value is `true`.
|
/// The default value is `true`.
|
||||||
///
|
///
|
||||||
/// [`device_address`]: MemoryAllocateFlags::device_address
|
/// [`DEVICE_ADDRESS`]: MemoryAllocateFlags::DEVICE_ADDRESS
|
||||||
/// [`shader_device_address`]: crate::buffer::BufferUsage::shader_device_address
|
/// [`SHADER_DEVICE_ADDRESS`]: crate::buffer::BufferUsage::SHADER_DEVICE_ADDRESS
|
||||||
/// [`buffer_device_address`]: crate::device::Features::buffer_device_address
|
/// [`buffer_device_address`]: crate::device::Features::buffer_device_address
|
||||||
/// [`ext_buffer_device_address`]: crate::device::DeviceExtensions::ext_buffer_device_address
|
/// [`ext_buffer_device_address`]: crate::device::DeviceExtensions::ext_buffer_device_address
|
||||||
/// [`khr_device_group`]: crate::device::DeviceExtensions::khr_device_group
|
/// [`khr_device_group`]: crate::device::DeviceExtensions::khr_device_group
|
||||||
|
@ -18,7 +18,7 @@ use super::{array_vec::ArrayVec, AllocationCreateInfo, AllocationCreationError};
|
|||||||
use crate::{
|
use crate::{
|
||||||
device::{Device, DeviceOwned},
|
device::{Device, DeviceOwned},
|
||||||
image::ImageTiling,
|
image::ImageTiling,
|
||||||
memory::DeviceMemory,
|
memory::{DeviceMemory, MemoryPropertyFlags},
|
||||||
DeviceSize, OomError, VulkanError, VulkanObject,
|
DeviceSize, OomError, VulkanError, VulkanObject,
|
||||||
};
|
};
|
||||||
use crossbeam_queue::ArrayQueue;
|
use crossbeam_queue::ArrayQueue;
|
||||||
@ -102,7 +102,7 @@ impl MemoryAlloc {
|
|||||||
[memory_type_index as usize]
|
[memory_type_index as usize]
|
||||||
.property_flags;
|
.property_flags;
|
||||||
|
|
||||||
let mapped_ptr = if property_flags.host_visible {
|
let mapped_ptr = if property_flags.intersects(MemoryPropertyFlags::HOST_VISIBLE) {
|
||||||
let fns = device.fns();
|
let fns = device.fns();
|
||||||
let mut output = MaybeUninit::uninit();
|
let mut output = MaybeUninit::uninit();
|
||||||
// This is always valid because we are mapping the whole range.
|
// This is always valid because we are mapping the whole range.
|
||||||
@ -124,9 +124,10 @@ impl MemoryAlloc {
|
|||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let atom_size = (property_flags.host_visible && !property_flags.host_coherent)
|
let atom_size = (property_flags.intersects(MemoryPropertyFlags::HOST_VISIBLE)
|
||||||
.then_some(physical_device.properties().non_coherent_atom_size)
|
&& !property_flags.intersects(MemoryPropertyFlags::HOST_COHERENT))
|
||||||
.and_then(NonZeroU64::new);
|
.then_some(physical_device.properties().non_coherent_atom_size)
|
||||||
|
.and_then(NonZeroU64::new);
|
||||||
|
|
||||||
Ok(MemoryAlloc {
|
Ok(MemoryAlloc {
|
||||||
offset: 0,
|
offset: 0,
|
||||||
@ -225,7 +226,7 @@ impl MemoryAlloc {
|
|||||||
/// - Panics if `range.end` exceeds `self.size`.
|
/// - Panics if `range.end` exceeds `self.size`.
|
||||||
/// - Panics if `range.start` or `range.end` are not a multiple of the `non_coherent_atom_size`.
|
/// - Panics if `range.start` or `range.end` are not a multiple of the `non_coherent_atom_size`.
|
||||||
///
|
///
|
||||||
/// [host-coherent]: super::MemoryPropertyFlags::host_coherent
|
/// [host-coherent]: crate::memory::MemoryPropertyFlags::HOST_COHERENT
|
||||||
/// [`non_coherent_atom_size`]: crate::device::Properties::non_coherent_atom_size
|
/// [`non_coherent_atom_size`]: crate::device::Properties::non_coherent_atom_size
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn invalidate_range(&self, range: Range<DeviceSize>) -> Result<(), OomError> {
|
pub unsafe fn invalidate_range(&self, range: Range<DeviceSize>) -> Result<(), OomError> {
|
||||||
@ -266,7 +267,7 @@ impl MemoryAlloc {
|
|||||||
/// - Panics if `range.end` exceeds `self.size`.
|
/// - Panics if `range.end` exceeds `self.size`.
|
||||||
/// - Panics if `range.start` or `range.end` are not a multiple of the `non_coherent_atom_size`.
|
/// - Panics if `range.start` or `range.end` are not a multiple of the `non_coherent_atom_size`.
|
||||||
///
|
///
|
||||||
/// [host-coherent]: super::MemoryPropertyFlags::host_coherent
|
/// [host-coherent]: crate::memory::MemoryPropertyFlags::HOST_COHERENT
|
||||||
/// [`non_coherent_atom_size`]: crate::device::Properties::non_coherent_atom_size
|
/// [`non_coherent_atom_size`]: crate::device::Properties::non_coherent_atom_size
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn flush_range(&self, range: Range<DeviceSize>) -> Result<(), OomError> {
|
pub unsafe fn flush_range(&self, range: Range<DeviceSize>) -> Result<(), OomError> {
|
||||||
@ -605,7 +606,7 @@ unsafe impl DeviceOwned for MemoryAlloc {
|
|||||||
/// Allocating a region to suballocatate:
|
/// Allocating a region to suballocatate:
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use vulkano::memory::{DeviceMemory, MemoryAllocateInfo, MemoryType};
|
/// use vulkano::memory::{DeviceMemory, MemoryAllocateInfo, MemoryPropertyFlags, MemoryType};
|
||||||
/// use vulkano::memory::allocator::MemoryAlloc;
|
/// use vulkano::memory::allocator::MemoryAlloc;
|
||||||
/// # let device: std::sync::Arc<vulkano::device::Device> = return;
|
/// # let device: std::sync::Arc<vulkano::device::Device> = return;
|
||||||
///
|
///
|
||||||
@ -620,7 +621,7 @@ unsafe impl DeviceOwned for MemoryAlloc {
|
|||||||
/// // requirements, instead of picking the first one that satisfies them. Also, you have to
|
/// // requirements, instead of picking the first one that satisfies them. Also, you have to
|
||||||
/// // take the requirements of the resources you want to allocate memory for into consideration.
|
/// // take the requirements of the resources you want to allocate memory for into consideration.
|
||||||
/// .find_map(|(index, MemoryType { property_flags, .. })| {
|
/// .find_map(|(index, MemoryType { property_flags, .. })| {
|
||||||
/// property_flags.device_local.then_some(index)
|
/// property_flags.intersects(MemoryPropertyFlags::DEVICE_LOCAL).then_some(index)
|
||||||
/// })
|
/// })
|
||||||
/// .unwrap() as u32;
|
/// .unwrap() as u32;
|
||||||
///
|
///
|
||||||
|
@ -10,7 +10,8 @@
|
|||||||
use super::{DedicatedAllocation, DedicatedTo};
|
use super::{DedicatedAllocation, DedicatedTo};
|
||||||
use crate::{
|
use crate::{
|
||||||
device::{Device, DeviceOwned},
|
device::{Device, DeviceOwned},
|
||||||
macros::{vulkan_bitflags, vulkan_enum},
|
macros::{vulkan_bitflags, vulkan_bitflags_enum},
|
||||||
|
memory::MemoryPropertyFlags,
|
||||||
DeviceSize, OomError, RequirementNotMet, RequiresOneOf, Version, VulkanError, VulkanObject,
|
DeviceSize, OomError, RequirementNotMet, RequiresOneOf, Version, VulkanError, VulkanObject,
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
@ -173,10 +174,14 @@ impl DeviceMemory {
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
// VUID-VkMemoryAllocateInfo-memoryTypeIndex-01872
|
// VUID-VkMemoryAllocateInfo-memoryTypeIndex-01872
|
||||||
if memory_type.property_flags.protected && !device.enabled_features().protected_memory {
|
if memory_type
|
||||||
|
.property_flags
|
||||||
|
.intersects(MemoryPropertyFlags::PROTECTED)
|
||||||
|
&& !device.enabled_features().protected_memory
|
||||||
|
{
|
||||||
return Err(DeviceMemoryError::RequirementNotMet {
|
return Err(DeviceMemoryError::RequirementNotMet {
|
||||||
required_for: "`allocate_info.memory_type_index` refers to a memory type where \
|
required_for: "`allocate_info.memory_type_index` refers to a memory type where \
|
||||||
`property_flags.protected` is set",
|
`property_flags` contains `MemoryPropertyFlags::PROTECTED`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["protected_memory"],
|
features: &["protected_memory"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -197,12 +202,14 @@ impl DeviceMemory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VUID-vkAllocateMemory-deviceCoherentMemory-02790
|
// VUID-vkAllocateMemory-deviceCoherentMemory-02790
|
||||||
if memory_type.property_flags.device_coherent
|
if memory_type
|
||||||
|
.property_flags
|
||||||
|
.intersects(MemoryPropertyFlags::DEVICE_COHERENT)
|
||||||
&& !device.enabled_features().device_coherent_memory
|
&& !device.enabled_features().device_coherent_memory
|
||||||
{
|
{
|
||||||
return Err(DeviceMemoryError::RequirementNotMet {
|
return Err(DeviceMemoryError::RequirementNotMet {
|
||||||
required_for: "`allocate_info.memory_type_index` refers to a memory type where \
|
required_for: "`allocate_info.memory_type_index` refers to a memory type where \
|
||||||
`property_flags.device_coherent` is set",
|
`property_flags` contains `MemoryPropertyFlags::DEVICE_COHERENT`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["device_coherent_memory"],
|
features: &["device_coherent_memory"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -278,8 +285,8 @@ impl DeviceMemory {
|
|||||||
} => {
|
} => {
|
||||||
if !device.enabled_extensions().khr_external_memory_fd {
|
if !device.enabled_extensions().khr_external_memory_fd {
|
||||||
return Err(DeviceMemoryError::RequirementNotMet {
|
return Err(DeviceMemoryError::RequirementNotMet {
|
||||||
required_for:
|
required_for: "`allocate_info.import_info` is \
|
||||||
"`allocate_info.import_info` is `Some(MemoryImportInfo::Fd)`",
|
`Some(MemoryImportInfo::Fd)`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
device_extensions: &["khr_external_memory_fd"],
|
device_extensions: &["khr_external_memory_fd"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -330,8 +337,8 @@ impl DeviceMemory {
|
|||||||
} => {
|
} => {
|
||||||
if !device.enabled_extensions().khr_external_memory_win32 {
|
if !device.enabled_extensions().khr_external_memory_win32 {
|
||||||
return Err(DeviceMemoryError::RequirementNotMet {
|
return Err(DeviceMemoryError::RequirementNotMet {
|
||||||
required_for:
|
required_for: "`allocate_info.import_info` is \
|
||||||
"`allocate_info.import_info` is `Some(MemoryImportInfo::Win32)`",
|
`Some(MemoryImportInfo::Win32)`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
device_extensions: &["khr_external_memory_win32"],
|
device_extensions: &["khr_external_memory_win32"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -390,11 +397,12 @@ impl DeviceMemory {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if flags.device_address {
|
if flags.intersects(MemoryAllocateFlags::DEVICE_ADDRESS) {
|
||||||
// VUID-VkMemoryAllocateInfo-flags-03331
|
// VUID-VkMemoryAllocateInfo-flags-03331
|
||||||
if !device.enabled_features().buffer_device_address {
|
if !device.enabled_features().buffer_device_address {
|
||||||
return Err(DeviceMemoryError::RequirementNotMet {
|
return Err(DeviceMemoryError::RequirementNotMet {
|
||||||
required_for: "`allocate_info.flags.device_address` is `true`",
|
required_for: "`allocate_info.flags` contains \
|
||||||
|
`MemoryAllocateFlags::DEVICE_ADDRESS`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["buffer_device_address"],
|
features: &["buffer_device_address"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -404,7 +412,8 @@ impl DeviceMemory {
|
|||||||
|
|
||||||
if device.enabled_extensions().ext_buffer_device_address {
|
if device.enabled_extensions().ext_buffer_device_address {
|
||||||
return Err(DeviceMemoryError::RequirementNotMet {
|
return Err(DeviceMemoryError::RequirementNotMet {
|
||||||
required_for: "`allocate_info.flags.device_address` is `true`",
|
required_for: "`allocate_info.flags` contains \
|
||||||
|
`MemoryAllocateFlags::DEVICE_ADDRESS`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
api_version: Some(Version::V1_2),
|
api_version: Some(Version::V1_2),
|
||||||
device_extensions: &["khr_buffer_device_address"],
|
device_extensions: &["khr_buffer_device_address"],
|
||||||
@ -609,8 +618,10 @@ impl DeviceMemory {
|
|||||||
/// The device may change this value at any time, and the returned value may be
|
/// The device may change this value at any time, and the returned value may be
|
||||||
/// already out-of-date.
|
/// already out-of-date.
|
||||||
///
|
///
|
||||||
/// `self` must have been allocated from a memory type that has the
|
/// `self` must have been allocated from a memory type that has the [`LAZILY_ALLOCATED`] flag
|
||||||
/// [`lazily_allocated`](crate::memory::MemoryPropertyFlags::lazily_allocated) flag set.
|
/// set.
|
||||||
|
///
|
||||||
|
/// [`LAZILY_ALLOCATED`]: crate::memory::MemoryPropertyFlags::LAZILY_ALLOCATED
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn commitment(&self) -> Result<DeviceSize, DeviceMemoryError> {
|
pub fn commitment(&self) -> Result<DeviceSize, DeviceMemoryError> {
|
||||||
self.validate_commitment()?;
|
self.validate_commitment()?;
|
||||||
@ -626,7 +637,10 @@ impl DeviceMemory {
|
|||||||
.memory_types[self.memory_type_index as usize];
|
.memory_types[self.memory_type_index as usize];
|
||||||
|
|
||||||
// VUID-vkGetDeviceMemoryCommitment-memory-00690
|
// VUID-vkGetDeviceMemoryCommitment-memory-00690
|
||||||
if !memory_type.property_flags.lazily_allocated {
|
if !memory_type
|
||||||
|
.property_flags
|
||||||
|
.intersects(MemoryPropertyFlags::LAZILY_ALLOCATED)
|
||||||
|
{
|
||||||
return Err(DeviceMemoryError::NotLazilyAllocated);
|
return Err(DeviceMemoryError::NotLazilyAllocated);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -855,212 +869,87 @@ pub enum MemoryImportInfo {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
vulkan_enum! {
|
vulkan_bitflags_enum! {
|
||||||
/// Describes a handle type used for Vulkan external memory apis. This is **not** just a
|
|
||||||
/// suggestion. Check out vkExternalMemoryHandleTypeFlagBits in the Vulkan spec.
|
|
||||||
///
|
|
||||||
/// If you specify an handle type that doesnt make sense (for example, using a dma-buf handle
|
|
||||||
/// type on Windows) when using this handle, a panic will happen.
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
ExternalMemoryHandleType = ExternalMemoryHandleTypeFlags(u32);
|
|
||||||
|
|
||||||
// TODO: document
|
/// A set of [`ExternalMemoryHandleType`] values.
|
||||||
OpaqueFd = OPAQUE_FD,
|
ExternalMemoryHandleTypes,
|
||||||
|
|
||||||
// TODO: document
|
/// A handle type used to export or import memory to/from an external source.
|
||||||
OpaqueWin32 = OPAQUE_WIN32,
|
ExternalMemoryHandleType,
|
||||||
|
|
||||||
// TODO: document
|
= ExternalMemoryHandleTypeFlags(u32);
|
||||||
OpaqueWin32Kmt = OPAQUE_WIN32_KMT,
|
|
||||||
|
|
||||||
// TODO: document
|
/// A POSIX file descriptor handle that is only usable with Vulkan and compatible APIs.
|
||||||
D3D11Texture = D3D11_TEXTURE,
|
OPAQUE_FD, OpaqueFd = OPAQUE_FD,
|
||||||
|
|
||||||
// TODO: document
|
/// A Windows NT handle that is only usable with Vulkan and compatible APIs.
|
||||||
D3D11TextureKmt = D3D11_TEXTURE_KMT,
|
OPAQUE_WIN32, OpaqueWin32 = OPAQUE_WIN32,
|
||||||
|
|
||||||
// TODO: document
|
/// A Windows global share handle that is only usable with Vulkan and compatible APIs.
|
||||||
D3D12Heap = D3D12_HEAP,
|
OPAQUE_WIN32_KMT, OpaqueWin32Kmt = OPAQUE_WIN32_KMT,
|
||||||
|
|
||||||
// TODO: document
|
/// A Windows NT handle that refers to a Direct3D 10 or 11 texture resource.
|
||||||
D3D12Resource = D3D12_RESOURCE,
|
D3D11_TEXTURE, D3D11Texture = D3D11_TEXTURE,
|
||||||
|
|
||||||
// TODO: document
|
/// A Windows global share handle that refers to a Direct3D 10 or 11 texture resource.
|
||||||
DmaBuf = DMA_BUF_EXT {
|
D3D11_TEXTURE_KMT, D3D11TextureKmt = D3D11_TEXTURE_KMT,
|
||||||
|
|
||||||
|
/// A Windows NT handle that refers to a Direct3D 12 heap resource.
|
||||||
|
D3D12_HEAP, D3D12Heap = D3D12_HEAP,
|
||||||
|
|
||||||
|
/// A Windows NT handle that refers to a Direct3D 12 committed resource.
|
||||||
|
D3D12_RESOURCE, D3D12Resource = D3D12_RESOURCE,
|
||||||
|
|
||||||
|
/// A POSIX file descriptor handle that refers to a Linux dma-buf.
|
||||||
|
DMA_BUF, DmaBuf = DMA_BUF_EXT {
|
||||||
device_extensions: [ext_external_memory_dma_buf],
|
device_extensions: [ext_external_memory_dma_buf],
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: document
|
/// A handle for an Android `AHardwareBuffer` object.
|
||||||
AndroidHardwareBuffer = ANDROID_HARDWARE_BUFFER_ANDROID {
|
ANDROID_HARDWARE_BUFFER, AndroidHardwareBuffer = ANDROID_HARDWARE_BUFFER_ANDROID {
|
||||||
device_extensions: [android_external_memory_android_hardware_buffer],
|
device_extensions: [android_external_memory_android_hardware_buffer],
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: document
|
/// A pointer to memory that was allocated by the host.
|
||||||
HostAllocation = HOST_ALLOCATION_EXT {
|
HOST_ALLOCATION, HostAllocation = HOST_ALLOCATION_EXT {
|
||||||
device_extensions: [ext_external_memory_host],
|
device_extensions: [ext_external_memory_host],
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: document
|
/// A pointer to a memory mapping on the host that maps non-host memory.
|
||||||
HostMappedForeignMemory = HOST_MAPPED_FOREIGN_MEMORY_EXT {
|
HOST_MAPPED_FOREIGN_MEMORY, HostMappedForeignMemory = HOST_MAPPED_FOREIGN_MEMORY_EXT {
|
||||||
device_extensions: [ext_external_memory_host],
|
device_extensions: [ext_external_memory_host],
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: document
|
/// A Zircon handle to a virtual memory object.
|
||||||
ZirconVmo = ZIRCON_VMO_FUCHSIA {
|
ZIRCON_VMO, ZirconVmo = ZIRCON_VMO_FUCHSIA {
|
||||||
device_extensions: [fuchsia_external_memory],
|
device_extensions: [fuchsia_external_memory],
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: document
|
/// A Remote Direct Memory Address handle to an allocation that is accessible by remote devices.
|
||||||
RdmaAddress = RDMA_ADDRESS_NV {
|
RDMA_ADDRESS, RdmaAddress = RDMA_ADDRESS_NV {
|
||||||
device_extensions: [nv_external_memory_rdma],
|
device_extensions: [nv_external_memory_rdma],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
vulkan_bitflags! {
|
vulkan_bitflags! {
|
||||||
/// A mask of multiple handle types.
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
ExternalMemoryHandleTypes = ExternalMemoryHandleTypeFlags(u32);
|
|
||||||
|
|
||||||
// TODO: document
|
|
||||||
opaque_fd = OPAQUE_FD,
|
|
||||||
|
|
||||||
// TODO: document
|
|
||||||
opaque_win32 = OPAQUE_WIN32,
|
|
||||||
|
|
||||||
// TODO: document
|
|
||||||
opaque_win32_kmt = OPAQUE_WIN32_KMT,
|
|
||||||
|
|
||||||
// TODO: document
|
|
||||||
d3d11_texture = D3D11_TEXTURE,
|
|
||||||
|
|
||||||
// TODO: document
|
|
||||||
d3d11_texture_kmt = D3D11_TEXTURE_KMT,
|
|
||||||
|
|
||||||
// TODO: document
|
|
||||||
d3d12_heap = D3D12_HEAP,
|
|
||||||
|
|
||||||
// TODO: document
|
|
||||||
d3d12_resource = D3D12_RESOURCE,
|
|
||||||
|
|
||||||
// TODO: document
|
|
||||||
dma_buf = DMA_BUF_EXT {
|
|
||||||
device_extensions: [ext_external_memory_dma_buf],
|
|
||||||
},
|
|
||||||
|
|
||||||
// TODO: document
|
|
||||||
android_hardware_buffer = ANDROID_HARDWARE_BUFFER_ANDROID {
|
|
||||||
device_extensions: [android_external_memory_android_hardware_buffer],
|
|
||||||
},
|
|
||||||
|
|
||||||
// TODO: document
|
|
||||||
host_allocation = HOST_ALLOCATION_EXT {
|
|
||||||
device_extensions: [ext_external_memory_host],
|
|
||||||
},
|
|
||||||
|
|
||||||
// TODO: document
|
|
||||||
host_mapped_foreign_memory = HOST_MAPPED_FOREIGN_MEMORY_EXT {
|
|
||||||
device_extensions: [ext_external_memory_host],
|
|
||||||
},
|
|
||||||
|
|
||||||
// TODO: document
|
|
||||||
zircon_vmo = ZIRCON_VMO_FUCHSIA {
|
|
||||||
device_extensions: [fuchsia_external_memory],
|
|
||||||
},
|
|
||||||
|
|
||||||
// TODO: document
|
|
||||||
rdma_address = RDMA_ADDRESS_NV {
|
|
||||||
device_extensions: [nv_external_memory_rdma],
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<ExternalMemoryHandleType> for ExternalMemoryHandleTypes {
|
|
||||||
#[inline]
|
|
||||||
fn from(val: ExternalMemoryHandleType) -> Self {
|
|
||||||
let mut result = Self::empty();
|
|
||||||
|
|
||||||
match val {
|
|
||||||
ExternalMemoryHandleType::OpaqueFd => result.opaque_fd = true,
|
|
||||||
ExternalMemoryHandleType::OpaqueWin32 => result.opaque_win32 = true,
|
|
||||||
ExternalMemoryHandleType::OpaqueWin32Kmt => result.opaque_win32_kmt = true,
|
|
||||||
ExternalMemoryHandleType::D3D11Texture => result.d3d11_texture = true,
|
|
||||||
ExternalMemoryHandleType::D3D11TextureKmt => result.d3d11_texture_kmt = true,
|
|
||||||
ExternalMemoryHandleType::D3D12Heap => result.d3d12_heap = true,
|
|
||||||
ExternalMemoryHandleType::D3D12Resource => result.d3d12_resource = true,
|
|
||||||
ExternalMemoryHandleType::DmaBuf => result.dma_buf = true,
|
|
||||||
ExternalMemoryHandleType::AndroidHardwareBuffer => {
|
|
||||||
result.android_hardware_buffer = true
|
|
||||||
}
|
|
||||||
ExternalMemoryHandleType::HostAllocation => result.host_allocation = true,
|
|
||||||
ExternalMemoryHandleType::HostMappedForeignMemory => {
|
|
||||||
result.host_mapped_foreign_memory = true
|
|
||||||
}
|
|
||||||
ExternalMemoryHandleType::ZirconVmo => result.zircon_vmo = true,
|
|
||||||
ExternalMemoryHandleType::RdmaAddress => result.rdma_address = true,
|
|
||||||
}
|
|
||||||
|
|
||||||
result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ExternalMemoryHandleTypes {
|
|
||||||
/// Returns an iterator of `ExternalMemoryHandleType` enum values, representing the fields that
|
|
||||||
/// are set in `self`.
|
|
||||||
#[inline]
|
|
||||||
pub fn iter(&self) -> impl Iterator<Item = ExternalMemoryHandleType> {
|
|
||||||
let ExternalMemoryHandleTypes {
|
|
||||||
opaque_fd,
|
|
||||||
opaque_win32,
|
|
||||||
opaque_win32_kmt,
|
|
||||||
d3d11_texture,
|
|
||||||
d3d11_texture_kmt,
|
|
||||||
d3d12_heap,
|
|
||||||
d3d12_resource,
|
|
||||||
dma_buf,
|
|
||||||
android_hardware_buffer,
|
|
||||||
host_allocation,
|
|
||||||
host_mapped_foreign_memory,
|
|
||||||
zircon_vmo,
|
|
||||||
rdma_address,
|
|
||||||
_ne: _,
|
|
||||||
} = *self;
|
|
||||||
|
|
||||||
[
|
|
||||||
opaque_fd.then_some(ExternalMemoryHandleType::OpaqueFd),
|
|
||||||
opaque_win32.then_some(ExternalMemoryHandleType::OpaqueWin32),
|
|
||||||
opaque_win32_kmt.then_some(ExternalMemoryHandleType::OpaqueWin32Kmt),
|
|
||||||
d3d11_texture.then_some(ExternalMemoryHandleType::D3D11Texture),
|
|
||||||
d3d11_texture_kmt.then_some(ExternalMemoryHandleType::D3D11TextureKmt),
|
|
||||||
d3d12_heap.then_some(ExternalMemoryHandleType::D3D12Heap),
|
|
||||||
d3d12_resource.then_some(ExternalMemoryHandleType::D3D12Resource),
|
|
||||||
dma_buf.then_some(ExternalMemoryHandleType::DmaBuf),
|
|
||||||
android_hardware_buffer.then_some(ExternalMemoryHandleType::AndroidHardwareBuffer),
|
|
||||||
host_allocation.then_some(ExternalMemoryHandleType::HostAllocation),
|
|
||||||
host_mapped_foreign_memory.then_some(ExternalMemoryHandleType::HostMappedForeignMemory),
|
|
||||||
zircon_vmo.then_some(ExternalMemoryHandleType::HostMappedForeignMemory),
|
|
||||||
rdma_address.then_some(ExternalMemoryHandleType::HostMappedForeignMemory),
|
|
||||||
]
|
|
||||||
.into_iter()
|
|
||||||
.flatten()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vulkan_bitflags! {
|
|
||||||
/// A mask specifying flags for device memory allocation.
|
/// A mask specifying flags for device memory allocation.
|
||||||
#[non_exhaustive]
|
|
||||||
MemoryAllocateFlags = MemoryAllocateFlags(u32);
|
MemoryAllocateFlags = MemoryAllocateFlags(u32);
|
||||||
|
|
||||||
// TODO: implement
|
// TODO: implement
|
||||||
// device_mask = DEVICE_MASK,
|
// device_mask = DEVICE_MASK,
|
||||||
|
|
||||||
/// Specifies that the allocated device memory can be bound to a buffer created with the
|
/// Specifies that the allocated device memory can be bound to a buffer created with the
|
||||||
/// [`shader_device_address`] usage. This requires that the [`buffer_device_address`] feature
|
/// [`SHADER_DEVICE_ADDRESS`] usage. This requires that the [`buffer_device_address`] feature
|
||||||
/// is enabled on the device and the [`ext_buffer_device_address`] extension is not enabled on
|
/// is enabled on the device and the [`ext_buffer_device_address`] extension is not enabled on
|
||||||
/// the device.
|
/// the device.
|
||||||
///
|
///
|
||||||
/// [`shader_device_address`]: crate::buffer::BufferUsage::shader_device_address
|
/// [`SHADER_DEVICE_ADDRESS`]: crate::buffer::BufferUsage::SHADER_DEVICE_ADDRESS
|
||||||
/// [`buffer_device_address`]: crate::device::Features::buffer_device_address
|
/// [`buffer_device_address`]: crate::device::Features::buffer_device_address
|
||||||
/// [`ext_buffer_device_address`]: crate::device::DeviceExtensions::ext_buffer_device_address
|
/// [`ext_buffer_device_address`]: crate::device::DeviceExtensions::ext_buffer_device_address
|
||||||
device_address = DEVICE_ADDRESS,
|
DEVICE_ADDRESS = DEVICE_ADDRESS,
|
||||||
|
|
||||||
// TODO: implement
|
// TODO: implement
|
||||||
// device_address_capture_replay = DEVICE_ADDRESS_CAPTURE_REPLAY,
|
// device_address_capture_replay = DEVICE_ADDRESS_CAPTURE_REPLAY,
|
||||||
@ -1119,8 +1008,10 @@ pub enum DeviceMemoryError {
|
|||||||
memory_type_count: u32,
|
memory_type_count: u32,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// The memory type from which this memory was allocated does not have the
|
/// The memory type from which this memory was allocated does not have the [`LAZILY_ALLOCATED`]
|
||||||
/// [`lazily_allocated`](crate::memory::MemoryPropertyFlags::lazily_allocated) flag set.
|
/// flag set.
|
||||||
|
///
|
||||||
|
/// [`LAZILY_ALLOCATED`]: crate::memory::MemoryPropertyFlags::LAZILY_ALLOCATED
|
||||||
NotLazilyAllocated,
|
NotLazilyAllocated,
|
||||||
|
|
||||||
/// Spec violation, containing the Valid Usage ID (VUID) from the Vulkan spec.
|
/// Spec violation, containing the Valid Usage ID (VUID) from the Vulkan spec.
|
||||||
@ -1259,7 +1150,7 @@ impl From<RequirementNotMet> for DeviceMemoryError {
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use vulkano::memory::{DeviceMemory, MappedDeviceMemory, MemoryAllocateInfo};
|
/// use vulkano::memory::{DeviceMemory, MappedDeviceMemory, MemoryAllocateInfo, MemoryPropertyFlags};
|
||||||
///
|
///
|
||||||
/// # let device: std::sync::Arc<vulkano::device::Device> = return;
|
/// # let device: std::sync::Arc<vulkano::device::Device> = return;
|
||||||
/// // The memory type must be mappable.
|
/// // The memory type must be mappable.
|
||||||
@ -1268,7 +1159,7 @@ impl From<RequirementNotMet> for DeviceMemoryError {
|
|||||||
/// .memory_properties()
|
/// .memory_properties()
|
||||||
/// .memory_types
|
/// .memory_types
|
||||||
/// .iter()
|
/// .iter()
|
||||||
/// .position(|t| t.property_flags.host_visible)
|
/// .position(|t| t.property_flags.intersects(MemoryPropertyFlags::HOST_VISIBLE))
|
||||||
/// .map(|i| i as u32)
|
/// .map(|i| i as u32)
|
||||||
/// .unwrap(); // Vk specs guarantee that this can't fail
|
/// .unwrap(); // Vk specs guarantee that this can't fail
|
||||||
///
|
///
|
||||||
@ -1342,11 +1233,16 @@ impl MappedDeviceMemory {
|
|||||||
[memory.memory_type_index() as usize];
|
[memory.memory_type_index() as usize];
|
||||||
|
|
||||||
// VUID-vkMapMemory-memory-00682
|
// VUID-vkMapMemory-memory-00682
|
||||||
if !memory_type.property_flags.host_visible {
|
if !memory_type
|
||||||
|
.property_flags
|
||||||
|
.intersects(MemoryPropertyFlags::HOST_VISIBLE)
|
||||||
|
{
|
||||||
return Err(MemoryMapError::NotHostVisible);
|
return Err(MemoryMapError::NotHostVisible);
|
||||||
}
|
}
|
||||||
|
|
||||||
let coherent = memory_type.property_flags.host_coherent;
|
let coherent = memory_type
|
||||||
|
.property_flags
|
||||||
|
.intersects(MemoryPropertyFlags::HOST_COHERENT);
|
||||||
let atom_size = device.physical_device().properties().non_coherent_atom_size;
|
let atom_size = device.physical_device().properties().non_coherent_atom_size;
|
||||||
|
|
||||||
// Not required for merely mapping, but without this check the user can end up with
|
// Not required for merely mapping, but without this check the user can end up with
|
||||||
@ -1687,7 +1583,7 @@ impl From<OomError> for MemoryMapError {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::MemoryAllocateInfo;
|
use super::MemoryAllocateInfo;
|
||||||
use crate::{
|
use crate::{
|
||||||
memory::{DeviceMemory, DeviceMemoryError},
|
memory::{DeviceMemory, DeviceMemoryError, MemoryPropertyFlags},
|
||||||
OomError,
|
OomError,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1731,7 +1627,11 @@ mod tests {
|
|||||||
.memory_types
|
.memory_types
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.find_map(|(i, m)| (!m.property_flags.lazily_allocated).then_some(i as u32))
|
.find_map(|(i, m)| {
|
||||||
|
(!m.property_flags
|
||||||
|
.intersects(MemoryPropertyFlags::LAZILY_ALLOCATED))
|
||||||
|
.then_some(i as u32)
|
||||||
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
match DeviceMemory::allocate(
|
match DeviceMemory::allocate(
|
||||||
@ -1757,7 +1657,11 @@ mod tests {
|
|||||||
.memory_types
|
.memory_types
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.find_map(|(i, m)| (!m.property_flags.lazily_allocated).then_some((i as u32, m)))
|
.find_map(|(i, m)| {
|
||||||
|
(!m.property_flags
|
||||||
|
.intersects(MemoryPropertyFlags::LAZILY_ALLOCATED))
|
||||||
|
.then_some((i as u32, m))
|
||||||
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let heap_size = device.physical_device().memory_properties().memory_heaps
|
let heap_size = device.physical_device().memory_properties().memory_heaps
|
||||||
[memory_type.heap_index as usize]
|
[memory_type.heap_index as usize]
|
||||||
|
@ -40,8 +40,7 @@
|
|||||||
//! # let physical_device: vulkano::device::physical::PhysicalDevice = return;
|
//! # let physical_device: vulkano::device::physical::PhysicalDevice = return;
|
||||||
//! for ty in physical_device.memory_properties().memory_types.iter() {
|
//! for ty in physical_device.memory_properties().memory_types.iter() {
|
||||||
//! println!("Memory type belongs to heap #{:?}", ty.heap_index);
|
//! println!("Memory type belongs to heap #{:?}", ty.heap_index);
|
||||||
//! println!("Host-accessible: {:?}", ty.property_flags.host_visible);
|
//! println!("Property flags: {:?}", ty.property_flags);
|
||||||
//! println!("Device-local: {:?}", ty.property_flags.device_local);
|
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
@ -153,12 +152,13 @@ pub struct MemoryType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vulkan_bitflags! {
|
vulkan_bitflags! {
|
||||||
/// Properties of a memory type.
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
|
|
||||||
|
/// Properties of a memory type.
|
||||||
MemoryPropertyFlags = MemoryPropertyFlags(u32);
|
MemoryPropertyFlags = MemoryPropertyFlags(u32);
|
||||||
|
|
||||||
/// The memory is located on the device, and is allocated from a heap that also has the
|
/// The memory is located on the device, and is allocated from a heap that also has the
|
||||||
/// [`device_local`](MemoryHeapFlags::device_local) flag set.
|
/// [`DEVICE_LOCAL`] flag set.
|
||||||
///
|
///
|
||||||
/// For some devices, particularly integrated GPUs, the device shares memory with the host and
|
/// For some devices, particularly integrated GPUs, the device shares memory with the host and
|
||||||
/// all memory may be device-local, so the distinction is moot. However, if the device has
|
/// all memory may be device-local, so the distinction is moot. However, if the device has
|
||||||
@ -174,41 +174,50 @@ vulkan_bitflags! {
|
|||||||
/// the speed difference may not be large.
|
/// the speed difference may not be large.
|
||||||
///
|
///
|
||||||
/// For data transfer between host and device, it is most efficient if the memory is located
|
/// For data transfer between host and device, it is most efficient if the memory is located
|
||||||
/// at the destination of the transfer. Thus, if `host_visible` versions of both are available,
|
/// at the destination of the transfer. Thus, if [`HOST_VISIBLE`] versions of both are
|
||||||
/// device-local memory is preferred for host-to-device data transfer, while non-device-local
|
/// available, device-local memory is preferred for host-to-device data transfer, while
|
||||||
/// memory is preferred for device-to-host data transfer. This is because data is usually
|
/// non-device-local memory is preferred for device-to-host data transfer. This is because data
|
||||||
/// written only once but potentially read several times, and because reads can take advantage
|
/// is usually written only once but potentially read several times, and because reads can take
|
||||||
/// of caching while writes cannot.
|
/// advantage of caching while writes cannot.
|
||||||
///
|
///
|
||||||
/// Devices may have memory types that are neither `device_local` nor `host_visible`. This is
|
/// Devices may have memory types that are neither `DEVICE_LOCAL` nor [`HOST_VISIBLE`]. This
|
||||||
/// regular host memory that is made available to the device exclusively. Although it will be
|
/// is regular host memory that is made available to the device exclusively. Although it will be
|
||||||
/// slower to access from the device than `device_local` memory, it can be faster than
|
/// slower to access from the device than `DEVICE_LOCAL` memory, it can be faster than
|
||||||
/// `host_visible` memory. It can be used as overflow space if the device is out of memory.
|
/// [`HOST_VISIBLE`] memory. It can be used as overflow space if the device is out of memory.
|
||||||
device_local = DEVICE_LOCAL,
|
///
|
||||||
|
/// [`DEVICE_LOCAL`]: MemoryHeapFlags::DEVICE_LOCAL
|
||||||
|
/// [`HOST_VISIBLE`]: MemoryPropertyFlags::HOST_VISIBLE
|
||||||
|
DEVICE_LOCAL = DEVICE_LOCAL,
|
||||||
|
|
||||||
/// The memory can be mapped into the memory space of the host and accessed as regular RAM.
|
/// The memory can be mapped into the memory space of the host and accessed as regular RAM.
|
||||||
///
|
///
|
||||||
/// Memory of this type is required to transfer data between the host and the device. If
|
/// Memory of this type is required to transfer data between the host and the device. If
|
||||||
/// the memory is going to be accessed by the device more than a few times, it is recommended
|
/// the memory is going to be accessed by the device more than a few times, it is recommended
|
||||||
/// to copy the data to non-`host_visible` memory first if it is available.
|
/// to copy the data to non-`HOST_VISIBLE` memory first if it is available.
|
||||||
///
|
///
|
||||||
/// `host_visible` memory is always at least either `host_coherent` or `host_cached`, but it
|
/// `HOST_VISIBLE` memory is always at least either [`HOST_COHERENT`] or [`HOST_CACHED`],
|
||||||
/// can be both.
|
/// but it can be both.
|
||||||
host_visible = HOST_VISIBLE,
|
///
|
||||||
|
/// [`HOST_COHERENT`]: MemoryPropertyFlags::HOST_COHERENT
|
||||||
|
/// [`HOST_CACHED`]: MemoryPropertyFlags::HOST_CACHED
|
||||||
|
HOST_VISIBLE = HOST_VISIBLE,
|
||||||
|
|
||||||
/// Host access to the memory does not require calling
|
/// Host access to the memory does not require calling [`invalidate_range`] to make device
|
||||||
/// [`invalidate_range`](MappedDeviceMemory::invalidate_range) to make device writes visible to
|
/// writes visible to the host, nor [`flush_range`] to flush host writes back to the device.
|
||||||
/// the host, nor [`flush_range`](MappedDeviceMemory::flush_range) to flush host writes back
|
///
|
||||||
/// to the device.
|
/// [`invalidate_range`]: MappedDeviceMemory::invalidate_range
|
||||||
host_coherent = HOST_COHERENT,
|
/// [`flush_range`]: MappedDeviceMemory::flush_range
|
||||||
|
HOST_COHERENT = HOST_COHERENT,
|
||||||
|
|
||||||
/// The memory is cached by the host.
|
/// The memory is cached by the host.
|
||||||
///
|
///
|
||||||
/// `host_cached` memory is fast for reads and random access from the host, so it is preferred
|
/// `HOST_CACHED` memory is fast for reads and random access from the host, so it is preferred
|
||||||
/// for device-to-host data transfer. Memory that is `host_visible` but not `host_cached` is
|
/// for device-to-host data transfer. Memory that is [`HOST_VISIBLE`] but not `HOST_CACHED` is
|
||||||
/// often slow for all accesses other than sequential writing, so it is more suited for
|
/// often slow for all accesses other than sequential writing, so it is more suited for
|
||||||
/// host-to-device transfer, and it is often beneficial to write the data in sequence.
|
/// host-to-device transfer, and it is often beneficial to write the data in sequence.
|
||||||
host_cached = HOST_CACHED,
|
///
|
||||||
|
/// [`HOST_VISIBLE`]: MemoryPropertyFlags::HOST_VISIBLE
|
||||||
|
HOST_CACHED = HOST_CACHED,
|
||||||
|
|
||||||
/// Allocations made from the memory are lazy.
|
/// Allocations made from the memory are lazy.
|
||||||
///
|
///
|
||||||
@ -218,13 +227,19 @@ vulkan_bitflags! {
|
|||||||
/// allocation.
|
/// allocation.
|
||||||
///
|
///
|
||||||
/// Memory of this type can only be used on images created with a certain flag, and is never
|
/// Memory of this type can only be used on images created with a certain flag, and is never
|
||||||
/// `host_visible`.
|
/// [`HOST_VISIBLE`].
|
||||||
lazily_allocated = LAZILY_ALLOCATED,
|
///
|
||||||
|
/// [`HOST_VISIBLE`]: MemoryPropertyFlags::HOST_VISIBLE
|
||||||
|
LAZILY_ALLOCATED = LAZILY_ALLOCATED,
|
||||||
|
|
||||||
/// The memory can only be accessed by the device, and allows protected queue access.
|
/// The memory can only be accessed by the device, and allows protected queue access.
|
||||||
///
|
///
|
||||||
/// Memory of this type is never `host_visible`, `host_coherent` or `host_cached`.
|
/// Memory of this type is never [`HOST_VISIBLE`], [`HOST_COHERENT`] or [`HOST_CACHED`].
|
||||||
protected = PROTECTED {
|
///
|
||||||
|
/// [`HOST_VISIBLE`]: MemoryPropertyFlags::HOST_VISIBLE
|
||||||
|
/// [`HOST_COHERENT`]: MemoryPropertyFlags::HOST_COHERENT
|
||||||
|
/// [`HOST_CACHED`]: MemoryPropertyFlags::HOST_CACHED
|
||||||
|
PROTECTED = PROTECTED {
|
||||||
api_version: V1_1,
|
api_version: V1_1,
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -233,19 +248,21 @@ vulkan_bitflags! {
|
|||||||
///
|
///
|
||||||
/// Memory of this type is slower to access by the device, so it is best avoided for general
|
/// Memory of this type is slower to access by the device, so it is best avoided for general
|
||||||
/// purpose use. Because of its coherence properties, however, it may be useful for debugging.
|
/// purpose use. Because of its coherence properties, however, it may be useful for debugging.
|
||||||
device_coherent = DEVICE_COHERENT_AMD {
|
DEVICE_COHERENT = DEVICE_COHERENT_AMD {
|
||||||
device_extensions: [amd_device_coherent_memory],
|
device_extensions: [amd_device_coherent_memory],
|
||||||
},
|
},
|
||||||
|
|
||||||
/// The memory is not cached on the device.
|
/// The memory is not cached on the device.
|
||||||
///
|
///
|
||||||
/// `device_uncached` memory is always also `device_coherent`.
|
/// `DEVICE_UNCACHED` memory is always also [`DEVICE_COHERENT`].
|
||||||
device_uncached = DEVICE_UNCACHED_AMD {
|
///
|
||||||
|
/// [`DEVICE_COHERENT`]: MemoryPropertyFlags::DEVICE_COHERENT
|
||||||
|
DEVICE_UNCACHED = DEVICE_UNCACHED_AMD {
|
||||||
device_extensions: [amd_device_coherent_memory],
|
device_extensions: [amd_device_coherent_memory],
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Other devices can access the memory via remote direct memory access (RDMA).
|
/// Other devices can access the memory via remote direct memory access (RDMA).
|
||||||
rdma_capable = RDMA_CAPABLE_NV {
|
RDMA_CAPABLE = RDMA_CAPABLE_NV {
|
||||||
device_extensions: [nv_external_memory_rdma],
|
device_extensions: [nv_external_memory_rdma],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -262,16 +279,17 @@ pub struct MemoryHeap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vulkan_bitflags! {
|
vulkan_bitflags! {
|
||||||
/// Attributes of a memory heap.
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
|
|
||||||
|
/// Attributes of a memory heap.
|
||||||
MemoryHeapFlags = MemoryHeapFlags(u32);
|
MemoryHeapFlags = MemoryHeapFlags(u32);
|
||||||
|
|
||||||
/// The heap corresponds to device-local memory.
|
/// The heap corresponds to device-local memory.
|
||||||
device_local = DEVICE_LOCAL,
|
DEVICE_LOCAL = DEVICE_LOCAL,
|
||||||
|
|
||||||
/// If used on a logical device that represents more than one physical device, allocations are
|
/// If used on a logical device that represents more than one physical device, allocations are
|
||||||
/// replicated across each physical device's instance of this heap.
|
/// replicated across each physical device's instance of this heap.
|
||||||
multi_instance = MULTI_INSTANCE {
|
MULTI_INSTANCE = MULTI_INSTANCE {
|
||||||
api_version: V1_1,
|
api_version: V1_1,
|
||||||
instance_extensions: [khr_device_group_creation],
|
instance_extensions: [khr_device_group_creation],
|
||||||
},
|
},
|
||||||
|
@ -491,10 +491,7 @@ mod tests {
|
|||||||
let memory_allocator = StandardMemoryAllocator::new_default(device.clone());
|
let memory_allocator = StandardMemoryAllocator::new_default(device.clone());
|
||||||
let data_buffer = CpuAccessibleBuffer::from_data(
|
let data_buffer = CpuAccessibleBuffer::from_data(
|
||||||
&memory_allocator,
|
&memory_allocator,
|
||||||
BufferUsage {
|
BufferUsage::STORAGE_BUFFER,
|
||||||
storage_buffer: true,
|
|
||||||
..BufferUsage::empty()
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
0,
|
0,
|
||||||
)
|
)
|
||||||
|
@ -34,7 +34,8 @@ use super::{
|
|||||||
use crate::{
|
use crate::{
|
||||||
descriptor_set::layout::{DescriptorSetLayout, DescriptorSetLayoutCreateInfo},
|
descriptor_set::layout::{DescriptorSetLayout, DescriptorSetLayoutCreateInfo},
|
||||||
device::{Device, DeviceOwned},
|
device::{Device, DeviceOwned},
|
||||||
format::NumericType,
|
format::{FormatFeatures, NumericType},
|
||||||
|
image::ImageAspects,
|
||||||
pipeline::{
|
pipeline::{
|
||||||
cache::PipelineCache,
|
cache::PipelineCache,
|
||||||
graphics::{
|
graphics::{
|
||||||
@ -484,7 +485,8 @@ where
|
|||||||
// VUID-VkGraphicsPipelineCreateInfo-multiview-06577
|
// VUID-VkGraphicsPipelineCreateInfo-multiview-06577
|
||||||
if view_mask != 0 && !device.enabled_features().multiview {
|
if view_mask != 0 && !device.enabled_features().multiview {
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for: "`render_pass` is `PipelineRenderPassType::BeginRendering` where `view_mask` is not `0`",
|
required_for: "`render_pass` is `PipelineRenderPassType::BeginRendering` \
|
||||||
|
where `view_mask` is not `0`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["multiview"],
|
features: &["multiview"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -519,7 +521,7 @@ where
|
|||||||
// Use unchecked, because all validation has been done above.
|
// Use unchecked, because all validation has been done above.
|
||||||
if !unsafe { physical_device.format_properties_unchecked(format) }
|
if !unsafe { physical_device.format_properties_unchecked(format) }
|
||||||
.potential_format_features()
|
.potential_format_features()
|
||||||
.color_attachment
|
.intersects(FormatFeatures::COLOR_ATTACHMENT)
|
||||||
{
|
{
|
||||||
return Err(
|
return Err(
|
||||||
GraphicsPipelineCreationError::ColorAttachmentFormatUsageNotSupported {
|
GraphicsPipelineCreationError::ColorAttachmentFormatUsageNotSupported {
|
||||||
@ -537,7 +539,7 @@ where
|
|||||||
// Use unchecked, because all validation has been done above.
|
// Use unchecked, because all validation has been done above.
|
||||||
if !unsafe { physical_device.format_properties_unchecked(format) }
|
if !unsafe { physical_device.format_properties_unchecked(format) }
|
||||||
.potential_format_features()
|
.potential_format_features()
|
||||||
.depth_stencil_attachment
|
.intersects(FormatFeatures::DEPTH_STENCIL_ATTACHMENT)
|
||||||
{
|
{
|
||||||
return Err(
|
return Err(
|
||||||
GraphicsPipelineCreationError::DepthAttachmentFormatUsageNotSupported,
|
GraphicsPipelineCreationError::DepthAttachmentFormatUsageNotSupported,
|
||||||
@ -545,7 +547,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VUID-VkGraphicsPipelineCreateInfo-renderPass-06587
|
// VUID-VkGraphicsPipelineCreateInfo-renderPass-06587
|
||||||
if !format.aspects().depth {
|
if !format.aspects().intersects(ImageAspects::DEPTH) {
|
||||||
return Err(
|
return Err(
|
||||||
GraphicsPipelineCreationError::DepthAttachmentFormatUsageNotSupported,
|
GraphicsPipelineCreationError::DepthAttachmentFormatUsageNotSupported,
|
||||||
);
|
);
|
||||||
@ -560,7 +562,7 @@ where
|
|||||||
// Use unchecked, because all validation has been done above.
|
// Use unchecked, because all validation has been done above.
|
||||||
if !unsafe { physical_device.format_properties_unchecked(format) }
|
if !unsafe { physical_device.format_properties_unchecked(format) }
|
||||||
.potential_format_features()
|
.potential_format_features()
|
||||||
.depth_stencil_attachment
|
.intersects(FormatFeatures::DEPTH_STENCIL_ATTACHMENT)
|
||||||
{
|
{
|
||||||
return Err(
|
return Err(
|
||||||
GraphicsPipelineCreationError::StencilAttachmentFormatUsageNotSupported,
|
GraphicsPipelineCreationError::StencilAttachmentFormatUsageNotSupported,
|
||||||
@ -568,7 +570,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VUID-VkGraphicsPipelineCreateInfo-renderPass-06588
|
// VUID-VkGraphicsPipelineCreateInfo-renderPass-06588
|
||||||
if !format.aspects().stencil {
|
if !format.aspects().intersects(ImageAspects::STENCIL) {
|
||||||
return Err(
|
return Err(
|
||||||
GraphicsPipelineCreationError::StencilAttachmentFormatUsageNotSupported,
|
GraphicsPipelineCreationError::StencilAttachmentFormatUsageNotSupported,
|
||||||
);
|
);
|
||||||
@ -663,7 +665,9 @@ where
|
|||||||
.vertex_attribute_instance_rate_divisor
|
.vertex_attribute_instance_rate_divisor
|
||||||
{
|
{
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for: "`vertex_input_state.bindings` has an element where `input_rate` is `VertexInputRate::Instance`, where `divisor` is not `1`",
|
required_for: "`vertex_input_state.bindings` has an element \
|
||||||
|
where `input_rate` is `VertexInputRate::Instance`, where \
|
||||||
|
`divisor` is not `1`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["vertex_attribute_instance_rate_divisor"],
|
features: &["vertex_attribute_instance_rate_divisor"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -678,7 +682,9 @@ where
|
|||||||
.vertex_attribute_instance_rate_zero_divisor
|
.vertex_attribute_instance_rate_zero_divisor
|
||||||
{
|
{
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for: "`vertex_input_state.bindings` has an element where `input_rate` is `VertexInputRate::Instance`, where `divisor` is `0`",
|
required_for: "`vertex_input_state.bindings` has an element \
|
||||||
|
where `input_rate` is `VertexInputRate::Instance`, where \
|
||||||
|
`divisor` is `0`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["vertex_attribute_instance_rate_zero_divisor"],
|
features: &["vertex_attribute_instance_rate_zero_divisor"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -754,7 +760,7 @@ where
|
|||||||
};
|
};
|
||||||
|
|
||||||
// VUID-VkVertexInputAttributeDescription-format-00623
|
// VUID-VkVertexInputAttributeDescription-format-00623
|
||||||
if !format_features.vertex_buffer {
|
if !format_features.intersects(FormatFeatures::VERTEX_BUFFER) {
|
||||||
return Err(
|
return Err(
|
||||||
GraphicsPipelineCreationError::VertexInputAttributeUnsupportedFormat {
|
GraphicsPipelineCreationError::VertexInputAttributeUnsupportedFormat {
|
||||||
location,
|
location,
|
||||||
@ -805,9 +811,8 @@ where
|
|||||||
&& !device.enabled_features().triangle_fans
|
&& !device.enabled_features().triangle_fans
|
||||||
{
|
{
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for:
|
required_for: "this device is a portability subset \
|
||||||
"this device is a portability subset device, and \
|
device, and `input_assembly_state.topology` is \
|
||||||
`input_assembly_state.topology` is \
|
|
||||||
`StateMode::Fixed(PrimitiveTopology::TriangleFan)`",
|
`StateMode::Fixed(PrimitiveTopology::TriangleFan)`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["triangle_fans"],
|
features: &["triangle_fans"],
|
||||||
@ -823,7 +828,8 @@ where
|
|||||||
// VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00429
|
// VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00429
|
||||||
if !device.enabled_features().geometry_shader {
|
if !device.enabled_features().geometry_shader {
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for: "`input_assembly_state.topology` is `StateMode::Fixed(PrimitiveTopology::*WithAdjacency)`",
|
required_for: "`input_assembly_state.topology` is \
|
||||||
|
`StateMode::Fixed(PrimitiveTopology::*WithAdjacency)`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["geometry_shader"],
|
features: &["geometry_shader"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -835,7 +841,8 @@ where
|
|||||||
// VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00430
|
// VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00430
|
||||||
if !device.enabled_features().tessellation_shader {
|
if !device.enabled_features().tessellation_shader {
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for: "`input_assembly_state.topology` is `StateMode::Fixed(PrimitiveTopology::PatchList)`",
|
required_for: "`input_assembly_state.topology` is \
|
||||||
|
`StateMode::Fixed(PrimitiveTopology::PatchList)`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["tessellation_shader"],
|
features: &["tessellation_shader"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -858,8 +865,8 @@ where
|
|||||||
|| device.enabled_features().extended_dynamic_state)
|
|| device.enabled_features().extended_dynamic_state)
|
||||||
{
|
{
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for:
|
required_for: "`input_assembly_state.topology` is \
|
||||||
"`input_assembly_state.topology` is `PartialStateMode::Dynamic`",
|
`PartialStateMode::Dynamic`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
api_version: Some(Version::V1_3),
|
api_version: Some(Version::V1_3),
|
||||||
features: &["extended_dynamic_state"],
|
features: &["extended_dynamic_state"],
|
||||||
@ -884,7 +891,10 @@ where
|
|||||||
// VUID-VkPipelineInputAssemblyStateCreateInfo-topology-06252
|
// VUID-VkPipelineInputAssemblyStateCreateInfo-topology-06252
|
||||||
if !device.enabled_features().primitive_topology_list_restart {
|
if !device.enabled_features().primitive_topology_list_restart {
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for: "`input_assembly_state.primitive_restart_enable` is `StateMode::Fixed(true)` and `input_assembly_state.topology` is `StateMode::Fixed(PrimitiveTopology::*List)`",
|
required_for: "`input_assembly_state.primitive_restart_enable` \
|
||||||
|
is `StateMode::Fixed(true)` and \
|
||||||
|
`input_assembly_state.topology` is \
|
||||||
|
`StateMode::Fixed(PrimitiveTopology::*List)`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["primitive_topology_list_restart"],
|
features: &["primitive_topology_list_restart"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -899,7 +909,10 @@ where
|
|||||||
.primitive_topology_patch_list_restart
|
.primitive_topology_patch_list_restart
|
||||||
{
|
{
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for: "`input_assembly_state.primitive_restart_enable` is `StateMode::Fixed(true)` and `input_assembly_state.topology` is `StateMode::Fixed(PrimitiveTopology::PatchList)`",
|
required_for: "`input_assembly_state.primitive_restart_enable` \
|
||||||
|
is `StateMode::Fixed(true)` and \
|
||||||
|
`input_assembly_state.topology` is \
|
||||||
|
`StateMode::Fixed(PrimitiveTopology::PatchList)`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["primitive_topology_patch_list_restart"],
|
features: &["primitive_topology_patch_list_restart"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -917,7 +930,8 @@ where
|
|||||||
|| device.enabled_features().extended_dynamic_state2)
|
|| device.enabled_features().extended_dynamic_state2)
|
||||||
{
|
{
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for: "`input_assembly_state.primitive_restart_enable` is `StateMode::Dynamic`",
|
required_for: "`input_assembly_state.primitive_restart_enable` is \
|
||||||
|
`StateMode::Dynamic`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
api_version: Some(Version::V1_3),
|
api_version: Some(Version::V1_3),
|
||||||
features: &["extended_dynamic_state2"],
|
features: &["extended_dynamic_state2"],
|
||||||
@ -1089,7 +1103,8 @@ where
|
|||||||
// VUID-VkGraphicsPipelineCreateInfo-renderPass-06057
|
// VUID-VkGraphicsPipelineCreateInfo-renderPass-06057
|
||||||
if view_mask != 0 {
|
if view_mask != 0 {
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for: "`tessellation_shaders` are provided and `render_pass` has a subpass where `view_mask` is not `0`",
|
required_for: "`tessellation_shaders` are provided and `render_pass` \
|
||||||
|
has a subpass where `view_mask` is not `0`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["multiview_tessellation_shader"],
|
features: &["multiview_tessellation_shader"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -1158,7 +1173,8 @@ where
|
|||||||
// VUID-VkGraphicsPipelineCreateInfo-renderPass-06058
|
// VUID-VkGraphicsPipelineCreateInfo-renderPass-06058
|
||||||
if view_mask != 0 {
|
if view_mask != 0 {
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for: "`geometry_shader` is provided and `render_pass` has a subpass where `view_mask` is not `0`",
|
required_for: "`geometry_shader` is provided and `render_pass` has a \
|
||||||
|
subpass where `view_mask` is not `0`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["multiview_geometry_shader"],
|
features: &["multiview_geometry_shader"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -1209,7 +1225,8 @@ where
|
|||||||
|| device.enabled_features().extended_dynamic_state2)
|
|| device.enabled_features().extended_dynamic_state2)
|
||||||
{
|
{
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for: "`rasterization_state.rasterizer_discard_enable` is `StateMode::Dynamic`",
|
required_for: "`rasterization_state.rasterizer_discard_enable` is \
|
||||||
|
`StateMode::Dynamic`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
api_version: Some(Version::V1_3),
|
api_version: Some(Version::V1_3),
|
||||||
features: &["extended_dynamic_state"],
|
features: &["extended_dynamic_state"],
|
||||||
@ -1244,8 +1261,8 @@ where
|
|||||||
&& !device.enabled_features().fill_mode_non_solid
|
&& !device.enabled_features().fill_mode_non_solid
|
||||||
{
|
{
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for:
|
required_for: "`rasterization_state.polygon_mode` is not \
|
||||||
"`rasterization_state.polygon_mode` is not `PolygonMode::Fill`",
|
`PolygonMode::Fill`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["fill_mode_non_solid"],
|
features: &["fill_mode_non_solid"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -1264,8 +1281,8 @@ where
|
|||||||
|| device.enabled_features().extended_dynamic_state)
|
|| device.enabled_features().extended_dynamic_state)
|
||||||
{
|
{
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for:
|
required_for: "`rasterization_state.cull_mode` is \
|
||||||
"`rasterization_state.cull_mode` is `StateMode::Dynamic`",
|
`StateMode::Dynamic`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
api_version: Some(Version::V1_3),
|
api_version: Some(Version::V1_3),
|
||||||
features: &["extended_dynamic_state"],
|
features: &["extended_dynamic_state"],
|
||||||
@ -1287,8 +1304,8 @@ where
|
|||||||
|| device.enabled_features().extended_dynamic_state)
|
|| device.enabled_features().extended_dynamic_state)
|
||||||
{
|
{
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for:
|
required_for: "`rasterization_state.front_face` is \
|
||||||
"`rasterization_state.front_face` is `StateMode::Dynamic`",
|
`StateMode::Dynamic`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
api_version: Some(Version::V1_3),
|
api_version: Some(Version::V1_3),
|
||||||
features: &["extended_dynamic_state"],
|
features: &["extended_dynamic_state"],
|
||||||
@ -1311,7 +1328,9 @@ where
|
|||||||
|| device.enabled_features().extended_dynamic_state2)
|
|| device.enabled_features().extended_dynamic_state2)
|
||||||
{
|
{
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for: "`rasterization_state.depth_bias` is `Some(depth_bias_state)`, where `depth_bias_state.enable_dynamic` is set",
|
required_for: "`rasterization_state.depth_bias` is \
|
||||||
|
`Some(depth_bias_state)`, where `depth_bias_state.enable_dynamic` \
|
||||||
|
is set",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
api_version: Some(Version::V1_3),
|
api_version: Some(Version::V1_3),
|
||||||
features: &["extended_dynamic_state2"],
|
features: &["extended_dynamic_state2"],
|
||||||
@ -1325,7 +1344,9 @@ where
|
|||||||
&& !device.enabled_features().depth_bias_clamp
|
&& !device.enabled_features().depth_bias_clamp
|
||||||
{
|
{
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for: "`rasterization_state.depth_bias` is `Some(depth_bias_state)`, where `depth_bias_state.bias` is `StateMode::Fixed(bias)`, where `bias.clamp` is not `0.0`",
|
required_for: "`rasterization_state.depth_bias` is \
|
||||||
|
`Some(depth_bias_state)`, where `depth_bias_state.bias` is \
|
||||||
|
`StateMode::Fixed(bias)`, where `bias.clamp` is not `0.0`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["depth_bias_clamp"],
|
features: &["depth_bias_clamp"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -1339,7 +1360,8 @@ where
|
|||||||
&& !device.enabled_features().wide_lines
|
&& !device.enabled_features().wide_lines
|
||||||
{
|
{
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for: "`rasterization_state.line_width` is `StateMode::Fixed(line_width)`, where `line_width` is not `1.0`",
|
required_for: "`rasterization_state.line_width` is \
|
||||||
|
`StateMode::Fixed(line_width)`, where `line_width` is not `1.0`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["wide_lines"],
|
features: &["wide_lines"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -1357,7 +1379,8 @@ where
|
|||||||
// VUID-VkPipelineRasterizationLineStateCreateInfoEXT-lineRasterizationMode-02768
|
// VUID-VkPipelineRasterizationLineStateCreateInfoEXT-lineRasterizationMode-02768
|
||||||
if !device.enabled_features().rectangular_lines {
|
if !device.enabled_features().rectangular_lines {
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for: "`rasterization_state.line_rasterization_mode` is `LineRasterizationMode::Rectangular`",
|
required_for: "`rasterization_state.line_rasterization_mode` \
|
||||||
|
is `LineRasterizationMode::Rectangular`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["rectangular_lines"],
|
features: &["rectangular_lines"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -1369,7 +1392,8 @@ where
|
|||||||
// VUID-VkPipelineRasterizationLineStateCreateInfoEXT-lineRasterizationMode-02769
|
// VUID-VkPipelineRasterizationLineStateCreateInfoEXT-lineRasterizationMode-02769
|
||||||
if !device.enabled_features().bresenham_lines {
|
if !device.enabled_features().bresenham_lines {
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for: "`rasterization_state.line_rasterization_mode` is `LineRasterizationMode::Bresenham`",
|
required_for: "`rasterization_state.line_rasterization_mode` \
|
||||||
|
is `LineRasterizationMode::Bresenham`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["bresenham_lines"],
|
features: &["bresenham_lines"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -1381,7 +1405,8 @@ where
|
|||||||
// VUID-VkPipelineRasterizationLineStateCreateInfoEXT-lineRasterizationMode-02770
|
// VUID-VkPipelineRasterizationLineStateCreateInfoEXT-lineRasterizationMode-02770
|
||||||
if !device.enabled_features().smooth_lines {
|
if !device.enabled_features().smooth_lines {
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for: "`rasterization_state.line_rasterization_mode` is `LineRasterizationMode::RectangularSmooth`",
|
required_for: "`rasterization_state.line_rasterization_mode` \
|
||||||
|
is `LineRasterizationMode::RectangularSmooth`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["smooth_lines"],
|
features: &["smooth_lines"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -1397,7 +1422,10 @@ where
|
|||||||
// VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02774
|
// VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02774
|
||||||
if !device.enabled_features().stippled_rectangular_lines {
|
if !device.enabled_features().stippled_rectangular_lines {
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for: "`rasterization_state.line_stipple` is `Some` and `rasterization_state.line_rasterization_mode` is `LineRasterizationMode::Default`",
|
required_for: "`rasterization_state.line_stipple` is \
|
||||||
|
`Some` and \
|
||||||
|
`rasterization_state.line_rasterization_mode` \
|
||||||
|
is `LineRasterizationMode::Default`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["stippled_rectangular_lines"],
|
features: &["stippled_rectangular_lines"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -1416,7 +1444,10 @@ where
|
|||||||
// VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02771
|
// VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02771
|
||||||
if !device.enabled_features().stippled_rectangular_lines {
|
if !device.enabled_features().stippled_rectangular_lines {
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for: "`rasterization_state.line_stipple` is `Some` and `rasterization_state.line_rasterization_mode` is `LineRasterizationMode::Rectangular`",
|
required_for: "`rasterization_state.line_stipple` is \
|
||||||
|
`Some` and \
|
||||||
|
`rasterization_state.line_rasterization_mode` \
|
||||||
|
is `LineRasterizationMode::Rectangular`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["stippled_rectangular_lines"],
|
features: &["stippled_rectangular_lines"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -1428,7 +1459,10 @@ where
|
|||||||
// VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02772
|
// VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02772
|
||||||
if !device.enabled_features().stippled_bresenham_lines {
|
if !device.enabled_features().stippled_bresenham_lines {
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for: "`rasterization_state.line_stipple` is `Some` and `rasterization_state.line_rasterization_mode` is `LineRasterizationMode::Bresenham`",
|
required_for: "`rasterization_state.line_stipple` is \
|
||||||
|
`Some` and \
|
||||||
|
`rasterization_state.line_rasterization_mode` \
|
||||||
|
is `LineRasterizationMode::Bresenham`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["stippled_bresenham_lines"],
|
features: &["stippled_bresenham_lines"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -1440,7 +1474,10 @@ where
|
|||||||
// VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02773
|
// VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02773
|
||||||
if !device.enabled_features().stippled_smooth_lines {
|
if !device.enabled_features().stippled_smooth_lines {
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for: "`rasterization_state.line_stipple` is `Some` and `rasterization_state.line_rasterization_mode` is `LineRasterizationMode::RectangularSmooth`",
|
required_for: "`rasterization_state.line_stipple` is \
|
||||||
|
`Some` and \
|
||||||
|
`rasterization_state.line_rasterization_mode` \
|
||||||
|
is `LineRasterizationMode::RectangularSmooth`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["stippled_smooth_lines"],
|
features: &["stippled_smooth_lines"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -1459,7 +1496,8 @@ where
|
|||||||
} else {
|
} else {
|
||||||
if line_rasterization_mode != LineRasterizationMode::Default {
|
if line_rasterization_mode != LineRasterizationMode::Default {
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for: "`rasterization_state.line_rasterization_mode` is not `LineRasterizationMode::Default`",
|
required_for: "`rasterization_state.line_rasterization_mode` is not \
|
||||||
|
`LineRasterizationMode::Default`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
device_extensions: &["ext_line_rasterization"],
|
device_extensions: &["ext_line_rasterization"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -1509,7 +1547,8 @@ where
|
|||||||
|
|
||||||
if error {
|
if error {
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for: "`discard_rectangle_state.rectangles` is not `PartialStateMode::Fixed(vec![])`",
|
required_for: "`discard_rectangle_state.rectangles` is not \
|
||||||
|
`PartialStateMode::Fixed(vec![])`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
device_extensions: &["ext_discard_rectangles"],
|
device_extensions: &["ext_discard_rectangles"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -1559,8 +1598,8 @@ where
|
|||||||
.extended_dynamic_state2_patch_control_points
|
.extended_dynamic_state2_patch_control_points
|
||||||
{
|
{
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for:
|
required_for: "`tessellation_state.patch_control_points` is \
|
||||||
"`tessellation_state.patch_control_points` is `StateMode::Dynamic`",
|
`StateMode::Dynamic`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["extended_dynamic_state2_patch_control_points"],
|
features: &["extended_dynamic_state2_patch_control_points"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -1637,7 +1676,9 @@ where
|
|||||||
|| device.enabled_features().extended_dynamic_state)
|
|| device.enabled_features().extended_dynamic_state)
|
||||||
{
|
{
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for: "`viewport_state` is `ViewportState::FixedViewport`, where `scissor_count_dynamic` is set",
|
required_for: "`viewport_state` is \
|
||||||
|
`ViewportState::FixedViewport`, where `scissor_count_dynamic` \
|
||||||
|
is set",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
api_version: Some(Version::V1_3),
|
api_version: Some(Version::V1_3),
|
||||||
features: &["extended_dynamic_state"],
|
features: &["extended_dynamic_state"],
|
||||||
@ -1669,7 +1710,9 @@ where
|
|||||||
|| device.enabled_features().extended_dynamic_state)
|
|| device.enabled_features().extended_dynamic_state)
|
||||||
{
|
{
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for: "`viewport_state` is `ViewportState::FixedScissor`, where `viewport_count_dynamic` is set",
|
required_for: "`viewport_state` is \
|
||||||
|
`ViewportState::FixedScissor`, where `viewport_count_dynamic` \
|
||||||
|
is set",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
api_version: Some(Version::V1_3),
|
api_version: Some(Version::V1_3),
|
||||||
features: &["extended_dynamic_state"],
|
features: &["extended_dynamic_state"],
|
||||||
@ -1707,7 +1750,9 @@ where
|
|||||||
|| device.enabled_features().extended_dynamic_state)
|
|| device.enabled_features().extended_dynamic_state)
|
||||||
{
|
{
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for: "`viewport_state` is `ViewportState::Dynamic`, where `viewport_count_dynamic` is set",
|
required_for: "`viewport_state` is \
|
||||||
|
`ViewportState::Dynamic`, where `viewport_count_dynamic` \
|
||||||
|
is set",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
api_version: Some(Version::V1_3),
|
api_version: Some(Version::V1_3),
|
||||||
features: &["extended_dynamic_state"],
|
features: &["extended_dynamic_state"],
|
||||||
@ -1728,7 +1773,9 @@ where
|
|||||||
|| device.enabled_features().extended_dynamic_state)
|
|| device.enabled_features().extended_dynamic_state)
|
||||||
{
|
{
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for: "`viewport_state` is `ViewportState::Dynamic`, where `scissor_count_dynamic` is set",
|
required_for: "`viewport_state` is \
|
||||||
|
`ViewportState::Dynamic`, where `scissor_count_dynamic` \
|
||||||
|
is set",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
api_version: Some(Version::V1_3),
|
api_version: Some(Version::V1_3),
|
||||||
features: &["extended_dynamic_state"],
|
features: &["extended_dynamic_state"],
|
||||||
@ -1756,7 +1803,8 @@ where
|
|||||||
// VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217
|
// VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217
|
||||||
if viewport_scissor_count > 1 && !device.enabled_features().multi_viewport {
|
if viewport_scissor_count > 1 && !device.enabled_features().multi_viewport {
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for: "`viewport_state` has a fixed viewport/scissor count that is greater than `1`",
|
required_for: "`viewport_state` has a fixed viewport/scissor count that is \
|
||||||
|
greater than `1`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["multi_viewport"],
|
features: &["multi_viewport"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -1867,8 +1915,8 @@ where
|
|||||||
|| device.enabled_features().extended_dynamic_state)
|
|| device.enabled_features().extended_dynamic_state)
|
||||||
{
|
{
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for:
|
required_for: "`depth_stencil_state.depth` is `Some(depth_state)`, where \
|
||||||
"`depth_stencil_state.depth` is `Some(depth_state)`, where `depth_state.enable_dynamic` is set",
|
`depth_state.enable_dynamic` is set",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
api_version: Some(Version::V1_3),
|
api_version: Some(Version::V1_3),
|
||||||
features: &["extended_dynamic_state"],
|
features: &["extended_dynamic_state"],
|
||||||
@ -1897,7 +1945,9 @@ where
|
|||||||
|| device.enabled_features().extended_dynamic_state)
|
|| device.enabled_features().extended_dynamic_state)
|
||||||
{
|
{
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for: "`depth_stencil_state.depth` is `Some(depth_state)`, where `depth_state.write_enable` is `StateMode::Dynamic`",
|
required_for: "`depth_stencil_state.depth` is \
|
||||||
|
`Some(depth_state)`, where `depth_state.write_enable` is \
|
||||||
|
`StateMode::Dynamic`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
api_version: Some(Version::V1_3),
|
api_version: Some(Version::V1_3),
|
||||||
features: &["extended_dynamic_state"],
|
features: &["extended_dynamic_state"],
|
||||||
@ -1919,7 +1969,9 @@ where
|
|||||||
|| device.enabled_features().extended_dynamic_state)
|
|| device.enabled_features().extended_dynamic_state)
|
||||||
{
|
{
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for: "`depth_stencil_state.depth` is `Some(depth_state)`, where `depth_state.compare_op` is `StateMode::Dynamic`",
|
required_for: "`depth_stencil_state.depth` is \
|
||||||
|
`Some(depth_state)`, where `depth_state.compare_op` is \
|
||||||
|
`StateMode::Dynamic`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
api_version: Some(Version::V1_3),
|
api_version: Some(Version::V1_3),
|
||||||
features: &["extended_dynamic_state"],
|
features: &["extended_dynamic_state"],
|
||||||
@ -1954,7 +2006,9 @@ where
|
|||||||
|| device.enabled_features().extended_dynamic_state)
|
|| device.enabled_features().extended_dynamic_state)
|
||||||
{
|
{
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for: "`depth_stencil_state.depth_bounds` is `Some(depth_bounds_state)`, where `depth_bounds_state.enable_dynamic` is set",
|
required_for: "`depth_stencil_state.depth_bounds` is \
|
||||||
|
`Some(depth_bounds_state)`, where `depth_bounds_state.enable_dynamic` \
|
||||||
|
is set",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
api_version: Some(Version::V1_3),
|
api_version: Some(Version::V1_3),
|
||||||
features: &["extended_dynamic_state"],
|
features: &["extended_dynamic_state"],
|
||||||
@ -1970,7 +2024,9 @@ where
|
|||||||
&& !(0.0..1.0).contains(bounds.end())
|
&& !(0.0..1.0).contains(bounds.end())
|
||||||
{
|
{
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for: "`depth_stencil_state.depth_bounds` is `Some(depth_bounds_state)`, where `depth_bounds_state.bounds` is not between `0.0` and `1.0` inclusive",
|
required_for: "`depth_stencil_state.depth_bounds` is \
|
||||||
|
`Some(depth_bounds_state)`, where `depth_bounds_state.bounds` is \
|
||||||
|
not between `0.0` and `1.0` inclusive",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
device_extensions: &["ext_depth_range_unrestricted"],
|
device_extensions: &["ext_depth_range_unrestricted"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -2004,8 +2060,8 @@ where
|
|||||||
|| device.enabled_features().extended_dynamic_state)
|
|| device.enabled_features().extended_dynamic_state)
|
||||||
{
|
{
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for:
|
required_for: "`depth_stencil_state.stencil` is `Some(stencil_state)`, \
|
||||||
"`depth_stencil_state.stencil` is `Some(stencil_state)`, where `stencil_state.enable_dynamic` is set",
|
where `stencil_state.enable_dynamic` is set",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
api_version: Some(Version::V1_3),
|
api_version: Some(Version::V1_3),
|
||||||
features: &["extended_dynamic_state"],
|
features: &["extended_dynamic_state"],
|
||||||
@ -2043,7 +2099,9 @@ where
|
|||||||
|| device.enabled_features().extended_dynamic_state)
|
|| device.enabled_features().extended_dynamic_state)
|
||||||
{
|
{
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for: "`depth_stencil_state.stencil` is `Some(stencil_state)`, where `stencil_state.front.ops` and `stencil_state.back.ops` are `StateMode::Dynamic`",
|
required_for: "`depth_stencil_state.stencil` is \
|
||||||
|
`Some(stencil_state)`, where `stencil_state.front.ops` and \
|
||||||
|
`stencil_state.back.ops` are `StateMode::Dynamic`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
api_version: Some(Version::V1_3),
|
api_version: Some(Version::V1_3),
|
||||||
features: &["extended_dynamic_state"],
|
features: &["extended_dynamic_state"],
|
||||||
@ -2209,8 +2267,8 @@ where
|
|||||||
// VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04869
|
// VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04869
|
||||||
if !device.enabled_features().extended_dynamic_state2_logic_op {
|
if !device.enabled_features().extended_dynamic_state2_logic_op {
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for:
|
required_for: "`color_blend_state.logic_op` is \
|
||||||
"`color_blend_state.logic_op` is `Some(StateMode::Dynamic)`",
|
`Some(StateMode::Dynamic)`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["extended_dynamic_state2_logic_op"],
|
features: &["extended_dynamic_state2_logic_op"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -2247,7 +2305,8 @@ where
|
|||||||
// VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605
|
// VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605
|
||||||
if !iter.all(|state| state == first) {
|
if !iter.all(|state| state == first) {
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for: "`color_blend_state.attachments` has elements where `blend` and `color_write_mask` do not match the other elements",
|
required_for: "`color_blend_state.attachments` has elements where \
|
||||||
|
`blend` and `color_write_mask` do not match the other elements",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["independent_blend"],
|
features: &["independent_blend"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -2312,9 +2371,9 @@ where
|
|||||||
{
|
{
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for: "`color_blend_state.attachments` has an element where \
|
required_for: "`color_blend_state.attachments` has an element where \
|
||||||
`blend` is `Some(blend)`, where `blend.color_source`, \
|
`blend` is `Some(blend)`, where `blend.color_source`, \
|
||||||
`blend.color_destination`, `blend.alpha_source` or \
|
`blend.color_destination`, `blend.alpha_source` or \
|
||||||
`blend.alpha_destination` is `BlendFactor::Src1*`",
|
`blend.alpha_destination` is `BlendFactor::Src1*`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["dual_src_blend"],
|
features: &["dual_src_blend"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -2344,7 +2403,7 @@ where
|
|||||||
physical_device
|
physical_device
|
||||||
.format_properties_unchecked(format)
|
.format_properties_unchecked(format)
|
||||||
.potential_format_features()
|
.potential_format_features()
|
||||||
.color_attachment_blend
|
.intersects(FormatFeatures::COLOR_ATTACHMENT_BLEND)
|
||||||
}) {
|
}) {
|
||||||
return Err(
|
return Err(
|
||||||
GraphicsPipelineCreationError::ColorAttachmentFormatBlendNotSupported {
|
GraphicsPipelineCreationError::ColorAttachmentFormatBlendNotSupported {
|
||||||
@ -2385,7 +2444,8 @@ where
|
|||||||
// VUID-VkPipelineColorWriteCreateInfoEXT-pAttachments-04801
|
// VUID-VkPipelineColorWriteCreateInfoEXT-pAttachments-04801
|
||||||
if !enable && !device.enabled_features().color_write_enable {
|
if !enable && !device.enabled_features().color_write_enable {
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for: "`color_blend_state.attachments` has an element where `color_write_enable` is `StateMode::Fixed(false)`",
|
required_for: "`color_blend_state.attachments` has an element \
|
||||||
|
where `color_write_enable` is `StateMode::Fixed(false)`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["color_write_enable"],
|
features: &["color_write_enable"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -2397,7 +2457,8 @@ where
|
|||||||
// VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04800
|
// VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04800
|
||||||
if !device.enabled_features().color_write_enable {
|
if !device.enabled_features().color_write_enable {
|
||||||
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
return Err(GraphicsPipelineCreationError::RequirementNotMet {
|
||||||
required_for: "`color_blend_state.attachments` has an element where `color_write_enable` is `StateMode::Dynamic`",
|
required_for: "`color_blend_state.attachments` has an element \
|
||||||
|
where `color_write_enable` is `StateMode::Dynamic`",
|
||||||
requires_one_of: RequiresOneOf {
|
requires_one_of: RequiresOneOf {
|
||||||
features: &["color_write_enable"],
|
features: &["color_write_enable"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -144,6 +144,7 @@ impl Default for ColorBlendState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vulkan_enum! {
|
vulkan_enum! {
|
||||||
|
#[non_exhaustive]
|
||||||
/// Which logical operation to apply to the output values.
|
/// Which logical operation to apply to the output values.
|
||||||
///
|
///
|
||||||
/// The operation is applied individually for each channel (red, green, blue and alpha).
|
/// The operation is applied individually for each channel (red, green, blue and alpha).
|
||||||
@ -151,7 +152,6 @@ vulkan_enum! {
|
|||||||
/// Only relevant for integer or unsigned attachments.
|
/// Only relevant for integer or unsigned attachments.
|
||||||
///
|
///
|
||||||
/// Also note that some implementations don't support logic operations.
|
/// Also note that some implementations don't support logic operations.
|
||||||
#[non_exhaustive]
|
|
||||||
LogicOp = LogicOp(i32);
|
LogicOp = LogicOp(i32);
|
||||||
|
|
||||||
/// Returns `0`.
|
/// Returns `0`.
|
||||||
@ -318,6 +318,8 @@ impl From<AttachmentBlend> for ash::vk::PipelineColorBlendAttachmentState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vulkan_enum! {
|
vulkan_enum! {
|
||||||
|
#[non_exhaustive]
|
||||||
|
|
||||||
/// The operation that takes `source` (output from the fragment shader), `destination` (value
|
/// The operation that takes `source` (output from the fragment shader), `destination` (value
|
||||||
/// currently in the framebuffer attachment) and `blend_constant` input values,
|
/// currently in the framebuffer attachment) and `blend_constant` input values,
|
||||||
/// and produces new inputs to be fed to `BlendOp`.
|
/// and produces new inputs to be fed to `BlendOp`.
|
||||||
@ -325,7 +327,6 @@ vulkan_enum! {
|
|||||||
/// Some operations take `source1` as an input, representing the second source value. The
|
/// Some operations take `source1` as an input, representing the second source value. The
|
||||||
/// [`dual_src_blend`](crate::device::Features::dual_src_blend) feature must be enabled on the
|
/// [`dual_src_blend`](crate::device::Features::dual_src_blend) feature must be enabled on the
|
||||||
/// device when these are used.
|
/// device when these are used.
|
||||||
#[non_exhaustive]
|
|
||||||
BlendFactor = BlendFactor(i32);
|
BlendFactor = BlendFactor(i32);
|
||||||
|
|
||||||
/// Always `0`.
|
/// Always `0`.
|
||||||
@ -400,9 +401,10 @@ vulkan_enum! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vulkan_enum! {
|
vulkan_enum! {
|
||||||
|
#[non_exhaustive]
|
||||||
|
|
||||||
/// The arithmetic operation that is applied between the `source` and `destination` component
|
/// The arithmetic operation that is applied between the `source` and `destination` component
|
||||||
/// values, after the appropriate `BlendFactor` is applied to both.
|
/// values, after the appropriate `BlendFactor` is applied to both.
|
||||||
#[non_exhaustive]
|
|
||||||
BlendOp = BlendOp(i32);
|
BlendOp = BlendOp(i32);
|
||||||
|
|
||||||
/// `source + destination`.
|
/// `source + destination`.
|
||||||
@ -658,14 +660,14 @@ vulkan_bitflags! {
|
|||||||
ColorComponents = ColorComponentFlags(u32);
|
ColorComponents = ColorComponentFlags(u32);
|
||||||
|
|
||||||
/// The red component.
|
/// The red component.
|
||||||
r = R,
|
R = R,
|
||||||
|
|
||||||
/// The green component.
|
/// The green component.
|
||||||
g = G,
|
G = G,
|
||||||
|
|
||||||
/// The blue component.
|
/// The blue component.
|
||||||
b = B,
|
B = B,
|
||||||
|
|
||||||
/// The alpha component.
|
/// The alpha component.
|
||||||
a = A,
|
A = A,
|
||||||
}
|
}
|
||||||
|
@ -251,8 +251,9 @@ impl Default for StencilOps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vulkan_enum! {
|
vulkan_enum! {
|
||||||
/// Operation to perform after the depth and stencil tests.
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
|
|
||||||
|
/// Operation to perform after the depth and stencil tests.
|
||||||
StencilOp = StencilOp(i32);
|
StencilOp = StencilOp(i32);
|
||||||
|
|
||||||
// TODO: document
|
// TODO: document
|
||||||
@ -281,8 +282,9 @@ vulkan_enum! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vulkan_enum! {
|
vulkan_enum! {
|
||||||
/// Specifies a face for stencil operations.
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
|
|
||||||
|
/// Specifies a face for stencil operations.
|
||||||
StencilFaces = StencilFaceFlags(u32);
|
StencilFaces = StencilFaceFlags(u32);
|
||||||
|
|
||||||
// TODO: document
|
// TODO: document
|
||||||
@ -303,10 +305,11 @@ pub struct DynamicStencilValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vulkan_enum! {
|
vulkan_enum! {
|
||||||
|
#[non_exhaustive]
|
||||||
|
|
||||||
/// Specifies how two values should be compared to decide whether a test passes or fails.
|
/// Specifies how two values should be compared to decide whether a test passes or fails.
|
||||||
///
|
///
|
||||||
/// Used for both depth testing and stencil testing.
|
/// Used for both depth testing and stencil testing.
|
||||||
#[non_exhaustive]
|
|
||||||
CompareOp = CompareOp(i32);
|
CompareOp = CompareOp(i32);
|
||||||
|
|
||||||
/// The test never passes.
|
/// The test never passes.
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user