use crate::{
buffer::Buffer,
descriptor_set::layout::DescriptorType,
device::{Device, QueueFlags},
image::{
Image, ImageAspects, ImageCreateFlags, ImageLayout, ImageSubresourceRange, ImageUsage,
},
macros::{vulkan_bitflags, vulkan_bitflags_enum},
shader::ShaderStages,
DeviceSize, Requires, RequiresAllOf, RequiresOneOf, ValidationError,
};
use ahash::HashMap;
use once_cell::sync::Lazy;
use smallvec::SmallVec;
use std::{ops::Range, sync::Arc};
vulkan_bitflags_enum! {
#[non_exhaustive]
PipelineStages impl {
pub(crate) fn contains_flags2(self) -> bool {
!(self
- (PipelineStages::TOP_OF_PIPE
| PipelineStages::DRAW_INDIRECT
| PipelineStages::VERTEX_INPUT
| PipelineStages::VERTEX_SHADER
| PipelineStages::TESSELLATION_CONTROL_SHADER
| PipelineStages::TESSELLATION_EVALUATION_SHADER
| PipelineStages::GEOMETRY_SHADER
| PipelineStages::FRAGMENT_SHADER
| PipelineStages::EARLY_FRAGMENT_TESTS
| PipelineStages::LATE_FRAGMENT_TESTS
| PipelineStages::COLOR_ATTACHMENT_OUTPUT
| PipelineStages::COMPUTE_SHADER
| PipelineStages::ALL_TRANSFER
| PipelineStages::BOTTOM_OF_PIPE
| PipelineStages::HOST
| PipelineStages::ALL_GRAPHICS
| PipelineStages::ALL_COMMANDS
| PipelineStages::TRANSFORM_FEEDBACK
| PipelineStages::CONDITIONAL_RENDERING
| PipelineStages::ACCELERATION_STRUCTURE_BUILD
| PipelineStages::RAY_TRACING_SHADER
| PipelineStages::FRAGMENT_DENSITY_PROCESS
| PipelineStages::FRAGMENT_SHADING_RATE_ATTACHMENT
| PipelineStages::COMMAND_PREPROCESS
| PipelineStages::TASK_SHADER
| PipelineStages::MESH_SHADER))
.is_empty()
}
pub(crate) fn expand(mut self, queue_flags: QueueFlags) -> Self {
if self.intersects(PipelineStages::ALL_COMMANDS) {
self -= PipelineStages::ALL_COMMANDS;
self |= queue_flags.into();
}
if self.intersects(PipelineStages::ALL_GRAPHICS) {
self -= PipelineStages::ALL_GRAPHICS;
self |= QueueFlags::GRAPHICS.into();
}
if self.intersects(PipelineStages::VERTEX_INPUT) {
self -= PipelineStages::VERTEX_INPUT;
self |= PipelineStages::INDEX_INPUT | PipelineStages::VERTEX_ATTRIBUTE_INPUT;
}
if self.intersects(PipelineStages::PRE_RASTERIZATION_SHADERS) {
self -= PipelineStages::PRE_RASTERIZATION_SHADERS;
self |= PipelineStages::VERTEX_SHADER
| PipelineStages::TESSELLATION_CONTROL_SHADER
| PipelineStages::TESSELLATION_EVALUATION_SHADER
| PipelineStages::GEOMETRY_SHADER
| PipelineStages::TASK_SHADER
| PipelineStages::MESH_SHADER;
}
if self.intersects(PipelineStages::ALL_TRANSFER) {
self -= PipelineStages::ALL_TRANSFER;
self |= PipelineStages::COPY
| PipelineStages::RESOLVE
| PipelineStages::BLIT
| PipelineStages::CLEAR
| PipelineStages::ACCELERATION_STRUCTURE_COPY;
}
self
}
pub(crate) fn into_supported(mut self, device: &Device) -> Self {
if !device.enabled_features().ray_tracing_maintenance1 {
if self.intersects(PipelineStages::ACCELERATION_STRUCTURE_COPY) {
self -= PipelineStages::ACCELERATION_STRUCTURE_COPY;
self |= PipelineStages::ACCELERATION_STRUCTURE_BUILD;
}
}
if !device.enabled_features().synchronization2 {
if self.intersects(
PipelineStages::INDEX_INPUT
| PipelineStages::VERTEX_ATTRIBUTE_INPUT
) {
self -= PipelineStages::INDEX_INPUT | PipelineStages::VERTEX_ATTRIBUTE_INPUT;
self |= PipelineStages::VERTEX_INPUT;
}
if self.intersects(
PipelineStages::COPY
| PipelineStages::RESOLVE
| PipelineStages::BLIT
| PipelineStages::CLEAR
) {
self -= PipelineStages::COPY
| PipelineStages::RESOLVE
| PipelineStages::BLIT
| PipelineStages::CLEAR;
self |= PipelineStages::ALL_TRANSFER;
}
if self.contains_flags2() {
if (self - PipelineStages::from(QueueFlags::GRAPHICS)).is_empty() {
return PipelineStages::ALL_GRAPHICS;
} else {
return PipelineStages::ALL_COMMANDS;
}
}
}
if self.validate_device(device).is_err() {
if (self - PipelineStages::from(QueueFlags::GRAPHICS)).is_empty() {
return PipelineStages::ALL_GRAPHICS;
} else {
return PipelineStages::ALL_COMMANDS;
}
}
self
}
},
PipelineStage,
= PipelineStageFlags2(u64);
TOP_OF_PIPE, TopOfPipe = TOP_OF_PIPE,
DRAW_INDIRECT, DrawIndirect = DRAW_INDIRECT,
VERTEX_INPUT, VertexInput = VERTEX_INPUT,
VERTEX_SHADER, VertexShader = VERTEX_SHADER,
TESSELLATION_CONTROL_SHADER, TessellationControlShader = TESSELLATION_CONTROL_SHADER,
TESSELLATION_EVALUATION_SHADER, TessellationEvaluationShader = TESSELLATION_EVALUATION_SHADER,
GEOMETRY_SHADER, GeometryShader = GEOMETRY_SHADER,
FRAGMENT_SHADER, FragmentShader = FRAGMENT_SHADER,
EARLY_FRAGMENT_TESTS, EarlyFragmentTests = EARLY_FRAGMENT_TESTS,
LATE_FRAGMENT_TESTS, LateFragmentTests = LATE_FRAGMENT_TESTS,
COLOR_ATTACHMENT_OUTPUT, ColorAttachmentOutput = COLOR_ATTACHMENT_OUTPUT,
COMPUTE_SHADER, ComputeShader = COMPUTE_SHADER,
ALL_TRANSFER, AllTransfer = ALL_TRANSFER,
BOTTOM_OF_PIPE, BottomOfPipe = BOTTOM_OF_PIPE,
HOST, Host = HOST,
ALL_GRAPHICS, AllGraphics = ALL_GRAPHICS,
ALL_COMMANDS, AllCommands = ALL_COMMANDS,
COPY, Copy = COPY
RequiresOneOf([
RequiresAllOf([APIVersion(V1_3)]),
RequiresAllOf([DeviceExtension(khr_synchronization2)]),
]),
RESOLVE, Resolve = RESOLVE
RequiresOneOf([
RequiresAllOf([APIVersion(V1_3)]),
RequiresAllOf([DeviceExtension(khr_synchronization2)]),
]),
BLIT, Blit = BLIT
RequiresOneOf([
RequiresAllOf([APIVersion(V1_3)]),
RequiresAllOf([DeviceExtension(khr_synchronization2)]),
]),
CLEAR, Clear = CLEAR
RequiresOneOf([
RequiresAllOf([APIVersion(V1_3)]),
RequiresAllOf([DeviceExtension(khr_synchronization2)]),
]),
INDEX_INPUT, IndexInput = INDEX_INPUT
RequiresOneOf([
RequiresAllOf([APIVersion(V1_3)]),
RequiresAllOf([DeviceExtension(khr_synchronization2)]),
]),
VERTEX_ATTRIBUTE_INPUT, VertexAttributeInput = VERTEX_ATTRIBUTE_INPUT
RequiresOneOf([
RequiresAllOf([APIVersion(V1_3)]),
RequiresAllOf([DeviceExtension(khr_synchronization2)]),
]),
PRE_RASTERIZATION_SHADERS, PreRasterizationShaders = PRE_RASTERIZATION_SHADERS
RequiresOneOf([
RequiresAllOf([APIVersion(V1_3)]),
RequiresAllOf([DeviceExtension(khr_synchronization2)]),
]),
VIDEO_DECODE, VideoDecode = VIDEO_DECODE_KHR
RequiresOneOf([
RequiresAllOf([DeviceExtension(khr_video_decode_queue)]),
]),
VIDEO_ENCODE, VideoEncode = VIDEO_ENCODE_KHR
RequiresOneOf([
RequiresAllOf([DeviceExtension(khr_video_encode_queue)]),
]),
TRANSFORM_FEEDBACK, TransformFeedback = TRANSFORM_FEEDBACK_EXT
RequiresOneOf([
RequiresAllOf([DeviceExtension(ext_transform_feedback)]),
]),
CONDITIONAL_RENDERING, ConditionalRendering = CONDITIONAL_RENDERING_EXT
RequiresOneOf([
RequiresAllOf([DeviceExtension(ext_conditional_rendering)]),
]),
ACCELERATION_STRUCTURE_BUILD, AccelerationStructureBuild = ACCELERATION_STRUCTURE_BUILD_KHR
RequiresOneOf([
RequiresAllOf([DeviceExtension(khr_acceleration_structure)]),
RequiresAllOf([DeviceExtension(nv_ray_tracing)]),
]),
RAY_TRACING_SHADER, RayTracingShader = RAY_TRACING_SHADER_KHR
RequiresOneOf([
RequiresAllOf([DeviceExtension(khr_ray_tracing_pipeline)]),
RequiresAllOf([DeviceExtension(nv_ray_tracing)]),
]),
FRAGMENT_DENSITY_PROCESS, FragmentDensityProcess = FRAGMENT_DENSITY_PROCESS_EXT
RequiresOneOf([
RequiresAllOf([DeviceExtension(ext_fragment_density_map)]),
]),
FRAGMENT_SHADING_RATE_ATTACHMENT, FragmentShadingRateAttachment = FRAGMENT_SHADING_RATE_ATTACHMENT_KHR
RequiresOneOf([
RequiresAllOf([DeviceExtension(khr_fragment_shading_rate)]),
]),
COMMAND_PREPROCESS, CommandPreprocess = COMMAND_PREPROCESS_NV
RequiresOneOf([
RequiresAllOf([DeviceExtension(nv_device_generated_commands)]),
]),
TASK_SHADER, TaskShader = TASK_SHADER_EXT
RequiresOneOf([
RequiresAllOf([DeviceExtension(ext_mesh_shader)]),
RequiresAllOf([DeviceExtension(nv_mesh_shader)]),
]),
MESH_SHADER, MeshShader = MESH_SHADER_EXT
RequiresOneOf([
RequiresAllOf([DeviceExtension(ext_mesh_shader)]),
RequiresAllOf([DeviceExtension(nv_mesh_shader)]),
]),
SUBPASS_SHADING, SubpassShading = SUBPASS_SHADING_HUAWEI
RequiresOneOf([
RequiresAllOf([
APIVersion(V1_3),
DeviceExtension(huawei_subpass_shading),
]),
RequiresAllOf([
DeviceExtension(khr_synchronization2),
DeviceExtension(huawei_subpass_shading),
]),
]),
INVOCATION_MASK, InvocationMask = INVOCATION_MASK_HUAWEI
RequiresOneOf([
RequiresAllOf([
APIVersion(V1_3),
DeviceExtension(huawei_invocation_mask),
]),
RequiresAllOf([
DeviceExtension(khr_synchronization2),
DeviceExtension(huawei_invocation_mask),
]),
]),
ACCELERATION_STRUCTURE_COPY, AccelerationStructureCopy = ACCELERATION_STRUCTURE_COPY_KHR
RequiresOneOf([
RequiresAllOf([DeviceExtension(khr_ray_tracing_maintenance1)]),
]),
MICROMAP_BUILD, MicromapBuild = MICROMAP_BUILD_EXT
RequiresOneOf([
RequiresAllOf([DeviceExtension(ext_opacity_micromap)]),
]),
OPTICAL_FLOW, OpticalFlow = OPTICAL_FLOW_NV
RequiresOneOf([
RequiresAllOf([DeviceExtension(nv_optical_flow)]),
]),
}
impl From<PipelineStage> for ash::vk::PipelineStageFlags {
#[inline]
fn from(val: PipelineStage) -> Self {
Self::from_raw(val as u32)
}
}
impl From<PipelineStages> for ash::vk::PipelineStageFlags {
#[inline]
fn from(val: PipelineStages) -> Self {
Self::from_raw(ash::vk::PipelineStageFlags2::from(val).as_raw() as u32)
}
}
impl From<QueueFlags> for PipelineStages {
#[inline]
fn from(val: QueueFlags) -> Self {
let mut result = PipelineStages::TOP_OF_PIPE
| PipelineStages::BOTTOM_OF_PIPE
| PipelineStages::HOST
| PipelineStages::ALL_COMMANDS;
if val.intersects(QueueFlags::GRAPHICS | QueueFlags::COMPUTE | QueueFlags::TRANSFER) {
result |= PipelineStages::ALL_TRANSFER
| PipelineStages::COPY
| PipelineStages::RESOLVE
| PipelineStages::BLIT
| PipelineStages::CLEAR
| PipelineStages::ACCELERATION_STRUCTURE_COPY;
}
if val.intersects(QueueFlags::GRAPHICS) {
result |= PipelineStages::DRAW_INDIRECT
| PipelineStages::VERTEX_INPUT
| PipelineStages::VERTEX_SHADER
| PipelineStages::TESSELLATION_CONTROL_SHADER
| PipelineStages::TESSELLATION_EVALUATION_SHADER
| PipelineStages::GEOMETRY_SHADER
| PipelineStages::FRAGMENT_SHADER
| PipelineStages::EARLY_FRAGMENT_TESTS
| PipelineStages::LATE_FRAGMENT_TESTS
| PipelineStages::COLOR_ATTACHMENT_OUTPUT
| PipelineStages::ALL_GRAPHICS
| PipelineStages::INDEX_INPUT
| PipelineStages::VERTEX_ATTRIBUTE_INPUT
| PipelineStages::PRE_RASTERIZATION_SHADERS
| PipelineStages::CONDITIONAL_RENDERING
| PipelineStages::TRANSFORM_FEEDBACK
| PipelineStages::COMMAND_PREPROCESS
| PipelineStages::FRAGMENT_SHADING_RATE_ATTACHMENT
| PipelineStages::TASK_SHADER
| PipelineStages::MESH_SHADER
| PipelineStages::FRAGMENT_DENSITY_PROCESS
| PipelineStages::SUBPASS_SHADING
| PipelineStages::INVOCATION_MASK;
}
if val.intersects(QueueFlags::COMPUTE) {
result |= PipelineStages::DRAW_INDIRECT
| PipelineStages::COMPUTE_SHADER
| PipelineStages::CONDITIONAL_RENDERING
| PipelineStages::COMMAND_PREPROCESS
| PipelineStages::ACCELERATION_STRUCTURE_BUILD
| PipelineStages::RAY_TRACING_SHADER
| PipelineStages::MICROMAP_BUILD;
}
if val.intersects(QueueFlags::VIDEO_DECODE) {
result |= PipelineStages::VIDEO_DECODE;
}
if val.intersects(QueueFlags::VIDEO_ENCODE) {
result |= PipelineStages::VIDEO_ENCODE;
}
if val.intersects(QueueFlags::OPTICAL_FLOW) {
result |= PipelineStages::OPTICAL_FLOW;
}
result
}
}
vulkan_bitflags! {
#[non_exhaustive]
AccessFlags impl {
const WRITES: AccessFlags = AccessFlags(
ash::vk::AccessFlags2::SHADER_WRITE.as_raw()
| ash::vk::AccessFlags2::COLOR_ATTACHMENT_WRITE.as_raw()
| ash::vk::AccessFlags2::DEPTH_STENCIL_ATTACHMENT_WRITE.as_raw()
| ash::vk::AccessFlags2::TRANSFER_WRITE.as_raw()
| ash::vk::AccessFlags2::HOST_WRITE.as_raw()
| ash::vk::AccessFlags2::MEMORY_WRITE.as_raw()
| ash::vk::AccessFlags2::SHADER_STORAGE_WRITE.as_raw()
| ash::vk::AccessFlags2::VIDEO_DECODE_WRITE_KHR.as_raw()
| ash::vk::AccessFlags2::VIDEO_ENCODE_WRITE_KHR.as_raw()
| ash::vk::AccessFlags2::TRANSFORM_FEEDBACK_WRITE_EXT.as_raw()
| ash::vk::AccessFlags2::TRANSFORM_FEEDBACK_COUNTER_WRITE_EXT.as_raw()
| ash::vk::AccessFlags2::COMMAND_PREPROCESS_WRITE_NV.as_raw()
| ash::vk::AccessFlags2::ACCELERATION_STRUCTURE_WRITE_KHR.as_raw()
);
pub(crate) fn contains_reads(self) -> bool {
!(self - Self::WRITES).is_empty()
}
pub(crate) fn contains_writes(self) -> bool {
self.intersects(Self::WRITES)
}
pub(crate) fn contains_flags2(self) -> bool {
!(self
- (AccessFlags::INDIRECT_COMMAND_READ
| AccessFlags::INDEX_READ
| AccessFlags::VERTEX_ATTRIBUTE_READ
| AccessFlags::UNIFORM_READ
| AccessFlags::INPUT_ATTACHMENT_READ
| AccessFlags::SHADER_READ
| AccessFlags::SHADER_WRITE
| AccessFlags::COLOR_ATTACHMENT_READ
| AccessFlags::COLOR_ATTACHMENT_WRITE
| AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ
| AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE
| AccessFlags::TRANSFER_READ
| AccessFlags::TRANSFER_WRITE
| AccessFlags::HOST_READ
| AccessFlags::HOST_WRITE
| AccessFlags::MEMORY_READ
| AccessFlags::MEMORY_WRITE
| AccessFlags::SHADER_SAMPLED_READ
| AccessFlags::SHADER_STORAGE_READ
| AccessFlags::SHADER_STORAGE_WRITE
| AccessFlags::VIDEO_DECODE_READ
| AccessFlags::VIDEO_DECODE_WRITE
| AccessFlags::VIDEO_ENCODE_READ
| AccessFlags::VIDEO_ENCODE_WRITE
| AccessFlags::TRANSFORM_FEEDBACK_WRITE
| AccessFlags::TRANSFORM_FEEDBACK_COUNTER_READ
| AccessFlags::TRANSFORM_FEEDBACK_COUNTER_WRITE
| AccessFlags::CONDITIONAL_RENDERING_READ
| AccessFlags::COMMAND_PREPROCESS_READ
| AccessFlags::COMMAND_PREPROCESS_WRITE
| AccessFlags::FRAGMENT_SHADING_RATE_ATTACHMENT_READ
| AccessFlags::ACCELERATION_STRUCTURE_READ
| AccessFlags::ACCELERATION_STRUCTURE_WRITE
| AccessFlags::FRAGMENT_DENSITY_MAP_READ
| AccessFlags::COLOR_ATTACHMENT_READ_NONCOHERENT
| AccessFlags::INVOCATION_MASK_READ))
.is_empty()
}
#[allow(dead_code)] pub(crate) fn expand(mut self) -> Self {
if self.intersects(AccessFlags::SHADER_READ) {
self -= AccessFlags::SHADER_READ;
self |= AccessFlags::SHADER_SAMPLED_READ
| AccessFlags::SHADER_STORAGE_READ
| AccessFlags::SHADER_BINDING_TABLE_READ;
}
if self.intersects(AccessFlags::SHADER_WRITE) {
self -= AccessFlags::SHADER_WRITE;
self |= AccessFlags::SHADER_STORAGE_WRITE;
}
self
}
pub(crate) fn into_supported(mut self, device: &Device) -> Self {
if !device.enabled_features().synchronization2 {
if self.intersects(
AccessFlags::SHADER_SAMPLED_READ
| AccessFlags::SHADER_STORAGE_READ
) {
self -= AccessFlags::SHADER_SAMPLED_READ | AccessFlags::SHADER_STORAGE_READ;
self |= AccessFlags::SHADER_READ;
}
if self.intersects(
AccessFlags::SHADER_STORAGE_WRITE
) {
self -= AccessFlags::SHADER_STORAGE_WRITE;
self |= AccessFlags::SHADER_WRITE;
}
if self.contains_flags2() {
return match (self.contains_reads(), self.contains_writes()) {
(true, true) => AccessFlags::MEMORY_READ | AccessFlags::MEMORY_WRITE,
(true, false) => AccessFlags::MEMORY_READ,
(false, true) => AccessFlags::MEMORY_WRITE,
(false, false) => unreachable!(),
};
}
}
if self.validate_device(device).is_err() {
return match (self.contains_reads(), self.contains_writes()) {
(true, true) => AccessFlags::MEMORY_READ | AccessFlags::MEMORY_WRITE,
(true, false) => AccessFlags::MEMORY_READ,
(false, true) => AccessFlags::MEMORY_WRITE,
(false, false) => unreachable!(),
};
}
self
}
}
= AccessFlags2(u64);
INDIRECT_COMMAND_READ = INDIRECT_COMMAND_READ,
INDEX_READ = INDEX_READ,
VERTEX_ATTRIBUTE_READ = VERTEX_ATTRIBUTE_READ,
UNIFORM_READ = UNIFORM_READ,
INPUT_ATTACHMENT_READ = INPUT_ATTACHMENT_READ,
SHADER_READ = SHADER_READ,
SHADER_WRITE = SHADER_WRITE,
COLOR_ATTACHMENT_READ = COLOR_ATTACHMENT_READ,
COLOR_ATTACHMENT_WRITE = COLOR_ATTACHMENT_WRITE,
DEPTH_STENCIL_ATTACHMENT_READ = DEPTH_STENCIL_ATTACHMENT_READ,
DEPTH_STENCIL_ATTACHMENT_WRITE = DEPTH_STENCIL_ATTACHMENT_WRITE,
TRANSFER_READ = TRANSFER_READ,
TRANSFER_WRITE = TRANSFER_WRITE,
HOST_READ = HOST_READ,
HOST_WRITE = HOST_WRITE,
MEMORY_READ = MEMORY_READ,
MEMORY_WRITE = MEMORY_WRITE,
SHADER_SAMPLED_READ = SHADER_SAMPLED_READ
RequiresOneOf([
RequiresAllOf([APIVersion(V1_3)]),
RequiresAllOf([DeviceExtension(khr_synchronization2)]),
]),
SHADER_STORAGE_READ = SHADER_STORAGE_READ
RequiresOneOf([
RequiresAllOf([APIVersion(V1_3)]),
RequiresAllOf([DeviceExtension(khr_synchronization2)]),
]),
SHADER_STORAGE_WRITE = SHADER_STORAGE_WRITE
RequiresOneOf([
RequiresAllOf([APIVersion(V1_3)]),
RequiresAllOf([DeviceExtension(khr_synchronization2)]),
]),
VIDEO_DECODE_READ = VIDEO_DECODE_READ_KHR
RequiresOneOf([
RequiresAllOf([
APIVersion(V1_3),
DeviceExtension(khr_video_decode_queue),
]),
RequiresAllOf([
DeviceExtension(khr_synchronization2),
DeviceExtension(khr_video_decode_queue),
]),
]),
VIDEO_DECODE_WRITE = VIDEO_DECODE_WRITE_KHR
RequiresOneOf([
RequiresAllOf([
APIVersion(V1_3),
DeviceExtension(khr_video_decode_queue),
]),
RequiresAllOf([
DeviceExtension(khr_synchronization2),
DeviceExtension(khr_video_decode_queue),
]),
]),
VIDEO_ENCODE_READ = VIDEO_ENCODE_READ_KHR
RequiresOneOf([
RequiresAllOf([
APIVersion(V1_3),
DeviceExtension(khr_video_encode_queue),
]),
RequiresAllOf([
DeviceExtension(khr_synchronization2),
DeviceExtension(khr_video_encode_queue),
]),
]),
VIDEO_ENCODE_WRITE = VIDEO_ENCODE_WRITE_KHR
RequiresOneOf([
RequiresAllOf([
APIVersion(V1_3),
DeviceExtension(khr_video_encode_queue),
]),
RequiresAllOf([
DeviceExtension(khr_synchronization2),
DeviceExtension(khr_video_encode_queue),
]),
]),
TRANSFORM_FEEDBACK_WRITE = TRANSFORM_FEEDBACK_WRITE_EXT
RequiresOneOf([
RequiresAllOf([DeviceExtension(ext_transform_feedback)]),
]),
TRANSFORM_FEEDBACK_COUNTER_READ = TRANSFORM_FEEDBACK_COUNTER_READ_EXT
RequiresOneOf([
RequiresAllOf([DeviceExtension(ext_transform_feedback)]),
]),
TRANSFORM_FEEDBACK_COUNTER_WRITE = TRANSFORM_FEEDBACK_COUNTER_WRITE_EXT
RequiresOneOf([
RequiresAllOf([DeviceExtension(ext_transform_feedback)]),
]),
CONDITIONAL_RENDERING_READ = CONDITIONAL_RENDERING_READ_EXT
RequiresOneOf([
RequiresAllOf([DeviceExtension(ext_conditional_rendering)]),
]),
COMMAND_PREPROCESS_READ = COMMAND_PREPROCESS_READ_NV
RequiresOneOf([
RequiresAllOf([DeviceExtension(nv_device_generated_commands)]),
]),
COMMAND_PREPROCESS_WRITE = COMMAND_PREPROCESS_WRITE_NV
RequiresOneOf([
RequiresAllOf([DeviceExtension(nv_device_generated_commands)]),
]),
FRAGMENT_SHADING_RATE_ATTACHMENT_READ = FRAGMENT_SHADING_RATE_ATTACHMENT_READ_KHR
RequiresOneOf([
RequiresAllOf([DeviceExtension(khr_fragment_shading_rate)]),
]),
ACCELERATION_STRUCTURE_READ = ACCELERATION_STRUCTURE_READ_KHR
RequiresOneOf([
RequiresAllOf([DeviceExtension(khr_acceleration_structure)]),
RequiresAllOf([DeviceExtension(nv_ray_tracing)]),
]),
ACCELERATION_STRUCTURE_WRITE = ACCELERATION_STRUCTURE_WRITE_KHR
RequiresOneOf([
RequiresAllOf([DeviceExtension(khr_acceleration_structure)]),
RequiresAllOf([DeviceExtension(nv_ray_tracing)]),
]),
FRAGMENT_DENSITY_MAP_READ = FRAGMENT_DENSITY_MAP_READ_EXT
RequiresOneOf([
RequiresAllOf([DeviceExtension(ext_fragment_density_map)]),
]),
COLOR_ATTACHMENT_READ_NONCOHERENT = COLOR_ATTACHMENT_READ_NONCOHERENT_EXT
RequiresOneOf([
RequiresAllOf([DeviceExtension(ext_blend_operation_advanced)]),
]),
INVOCATION_MASK_READ = INVOCATION_MASK_READ_HUAWEI
RequiresOneOf([
RequiresAllOf([
APIVersion(V1_3),
DeviceExtension(huawei_invocation_mask),
]),
RequiresAllOf([
DeviceExtension(khr_synchronization2),
DeviceExtension(huawei_invocation_mask),
]),
]),
SHADER_BINDING_TABLE_READ = SHADER_BINDING_TABLE_READ_KHR
RequiresOneOf([
RequiresAllOf([
APIVersion(V1_3),
DeviceExtension(khr_ray_tracing_pipeline),
DeviceExtension(khr_ray_tracing_maintenance1),
]),
RequiresAllOf([
DeviceExtension(khr_synchronization2),
DeviceExtension(khr_ray_tracing_pipeline),
DeviceExtension(khr_ray_tracing_maintenance1),
]),
]),
MICROMAP_READ = MICROMAP_READ_EXT
RequiresOneOf([
RequiresAllOf([
APIVersion(V1_3),
DeviceExtension(ext_opacity_micromap),
]),
RequiresAllOf([
DeviceExtension(khr_synchronization2),
DeviceExtension(ext_opacity_micromap),
]),
]),
MICROMAP_WRITE = MICROMAP_WRITE_EXT
RequiresOneOf([
RequiresAllOf([
APIVersion(V1_3),
DeviceExtension(ext_opacity_micromap),
]),
RequiresAllOf([
DeviceExtension(khr_synchronization2),
DeviceExtension(ext_opacity_micromap),
]),
]),
OPTICAL_FLOW_READ = OPTICAL_FLOW_READ_NV
RequiresOneOf([
RequiresAllOf([
APIVersion(V1_3),
DeviceExtension(nv_optical_flow),
]),
RequiresAllOf([
DeviceExtension(khr_synchronization2),
DeviceExtension(nv_optical_flow),
]),
]),
OPTICAL_FLOW_WRITE = OPTICAL_FLOW_WRITE_NV
RequiresOneOf([
RequiresAllOf([
APIVersion(V1_3),
DeviceExtension(nv_optical_flow),
]),
RequiresAllOf([
DeviceExtension(khr_synchronization2),
DeviceExtension(nv_optical_flow),
]),
]),
}
impl From<AccessFlags> for ash::vk::AccessFlags {
#[inline]
fn from(val: AccessFlags) -> Self {
Self::from_raw(ash::vk::AccessFlags2::from(val).as_raw() as u32)
}
}
impl From<PipelineStages> for AccessFlags {
#[inline]
fn from(mut val: PipelineStages) -> Self {
if val.is_empty() {
return AccessFlags::empty();
}
val = val.expand(QueueFlags::GRAPHICS | QueueFlags::COMPUTE | QueueFlags::TRANSFER);
let mut result = AccessFlags::MEMORY_READ | AccessFlags::MEMORY_WRITE;
if val.intersects(PipelineStages::DRAW_INDIRECT) {
result |=
AccessFlags::INDIRECT_COMMAND_READ | AccessFlags::TRANSFORM_FEEDBACK_COUNTER_READ;
}
if val.intersects(
PipelineStages::VERTEX_SHADER
| PipelineStages::TESSELLATION_CONTROL_SHADER
| PipelineStages::TESSELLATION_EVALUATION_SHADER
| PipelineStages::GEOMETRY_SHADER
| PipelineStages::FRAGMENT_SHADER
| PipelineStages::COMPUTE_SHADER
| PipelineStages::RAY_TRACING_SHADER
| PipelineStages::TASK_SHADER
| PipelineStages::MESH_SHADER,
) {
result |= AccessFlags::SHADER_READ
| AccessFlags::UNIFORM_READ
| AccessFlags::SHADER_SAMPLED_READ
| AccessFlags::SHADER_STORAGE_READ
| AccessFlags::SHADER_WRITE
| AccessFlags::SHADER_STORAGE_WRITE
| AccessFlags::ACCELERATION_STRUCTURE_READ;
}
if val.intersects(PipelineStages::FRAGMENT_SHADER | PipelineStages::SUBPASS_SHADING) {
result |= AccessFlags::INPUT_ATTACHMENT_READ;
}
if val
.intersects(PipelineStages::EARLY_FRAGMENT_TESTS | PipelineStages::LATE_FRAGMENT_TESTS)
{
result |= AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ
| AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE;
}
if val.intersects(PipelineStages::COLOR_ATTACHMENT_OUTPUT) {
result |= AccessFlags::COLOR_ATTACHMENT_READ
| AccessFlags::COLOR_ATTACHMENT_WRITE
| AccessFlags::COLOR_ATTACHMENT_READ_NONCOHERENT;
}
if val.intersects(PipelineStages::HOST) {
result |= AccessFlags::HOST_READ | AccessFlags::HOST_WRITE;
}
if val.intersects(
PipelineStages::COPY
| PipelineStages::RESOLVE
| PipelineStages::BLIT
| PipelineStages::ACCELERATION_STRUCTURE_COPY,
) {
result |= AccessFlags::TRANSFER_READ | AccessFlags::TRANSFER_WRITE;
}
if val.intersects(PipelineStages::CLEAR) {
result |= AccessFlags::TRANSFER_WRITE;
}
if val.intersects(PipelineStages::INDEX_INPUT) {
result |= AccessFlags::INDEX_READ;
}
if val.intersects(PipelineStages::VERTEX_ATTRIBUTE_INPUT) {
result |= AccessFlags::VERTEX_ATTRIBUTE_READ;
}
if val.intersects(PipelineStages::VIDEO_DECODE) {
result |= AccessFlags::VIDEO_DECODE_READ | AccessFlags::VIDEO_DECODE_WRITE;
}
if val.intersects(PipelineStages::VIDEO_ENCODE) {
result |= AccessFlags::VIDEO_ENCODE_READ | AccessFlags::VIDEO_ENCODE_WRITE;
}
if val.intersects(PipelineStages::TRANSFORM_FEEDBACK) {
result |= AccessFlags::TRANSFORM_FEEDBACK_WRITE
| AccessFlags::TRANSFORM_FEEDBACK_COUNTER_WRITE
| AccessFlags::TRANSFORM_FEEDBACK_COUNTER_READ;
}
if val.intersects(PipelineStages::CONDITIONAL_RENDERING) {
result |= AccessFlags::CONDITIONAL_RENDERING_READ;
}
if val.intersects(PipelineStages::ACCELERATION_STRUCTURE_BUILD) {
result |= AccessFlags::INDIRECT_COMMAND_READ
| AccessFlags::SHADER_READ
| AccessFlags::SHADER_SAMPLED_READ
| AccessFlags::SHADER_STORAGE_READ
| AccessFlags::SHADER_STORAGE_WRITE
| AccessFlags::TRANSFER_READ
| AccessFlags::TRANSFER_WRITE
| AccessFlags::ACCELERATION_STRUCTURE_READ
| AccessFlags::ACCELERATION_STRUCTURE_WRITE
| AccessFlags::MICROMAP_READ;
}
if val.intersects(PipelineStages::RAY_TRACING_SHADER) {
result |= AccessFlags::SHADER_BINDING_TABLE_READ;
}
if val.intersects(PipelineStages::FRAGMENT_DENSITY_PROCESS) {
result |= AccessFlags::FRAGMENT_DENSITY_MAP_READ;
}
if val.intersects(PipelineStages::FRAGMENT_SHADING_RATE_ATTACHMENT) {
result |= AccessFlags::FRAGMENT_SHADING_RATE_ATTACHMENT_READ;
}
if val.intersects(PipelineStages::COMMAND_PREPROCESS) {
result |= AccessFlags::COMMAND_PREPROCESS_READ | AccessFlags::COMMAND_PREPROCESS_WRITE;
}
if val.intersects(PipelineStages::INVOCATION_MASK) {
result |= AccessFlags::INVOCATION_MASK_READ;
}
if val.intersects(PipelineStages::MICROMAP_BUILD) {
result |= AccessFlags::MICROMAP_READ | AccessFlags::MICROMAP_WRITE;
}
if val.intersects(PipelineStages::OPTICAL_FLOW) {
result |= AccessFlags::OPTICAL_FLOW_READ | AccessFlags::OPTICAL_FLOW_WRITE;
}
result
}
}
macro_rules! pipeline_stage_access {
(
$(
$val:ident, $stage:ident, $access:ident
);*
$(;)?
) => {
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[allow(non_camel_case_types, dead_code)]
#[repr(u8)]
pub(crate) enum PipelineStageAccess {
$($val,)*
__MAX_VALUE__ = 128,
}
impl From<PipelineStageAccess> for PipelineStages {
#[inline]
fn from(val: PipelineStageAccess) -> Self {
match val {
$(
PipelineStageAccess::$val => PipelineStages::$stage,
)*
PipelineStageAccess::__MAX_VALUE__ => unreachable!(),
}
}
}
impl From<PipelineStageAccess> for AccessFlags {
#[inline]
fn from(val: PipelineStageAccess) -> Self {
match val {
$(
PipelineStageAccess::$val => AccessFlags::$access,
)*
PipelineStageAccess::__MAX_VALUE__ => unreachable!(),
}
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub(crate) struct PipelineStageAccessFlags(u128);
#[allow(non_upper_case_globals, dead_code)]
impl PipelineStageAccessFlags {
$(
pub(crate) const $val: Self = Self(1u128 << PipelineStageAccess::$val as u8);
)*
#[inline]
pub(crate) const fn empty() -> Self {
Self(0)
}
#[inline]
pub(crate) const fn count(self) -> u32 {
self.0.count_ones()
}
#[inline]
pub(crate) const fn is_empty(self) -> bool {
self.0 == 0
}
#[inline]
pub(crate) const fn intersects(self, other: Self) -> bool {
self.0 & other.0 != 0
}
#[inline]
pub(crate) const fn contains(self, other: Self) -> bool {
self.0 & other.0 == other.0
}
#[inline]
pub(crate) const fn union(self, other: Self) -> Self {
Self(self.0 | other.0)
}
#[inline]
pub(crate) const fn intersection(self, other: Self) -> Self {
Self(self.0 & other.0)
}
#[inline]
pub(crate) const fn difference(self, other: Self) -> Self {
Self(self.0 & !other.0)
}
#[inline]
pub(crate) const fn symmetric_difference(self, other: Self) -> Self {
Self(self.0 ^ other.0)
}
#[inline]
pub(crate) fn contains_enum(self, val: PipelineStageAccess) -> bool {
self.intersects(val.into())
}
}
impl std::ops::BitAnd for PipelineStageAccessFlags {
type Output = Self;
#[inline]
fn bitand(self, rhs: Self) -> Self {
self.intersection(rhs)
}
}
impl std::ops::BitAndAssign for PipelineStageAccessFlags {
#[inline]
fn bitand_assign(&mut self, rhs: Self) {
*self = self.intersection(rhs);
}
}
impl std::ops::BitOr for PipelineStageAccessFlags {
type Output = Self;
#[inline]
fn bitor(self, rhs: Self) -> Self {
self.union(rhs)
}
}
impl std::ops::BitOrAssign for PipelineStageAccessFlags {
#[inline]
fn bitor_assign(&mut self, rhs: Self) {
*self = self.union(rhs);
}
}
impl std::ops::BitXor for PipelineStageAccessFlags {
type Output = Self;
#[inline]
fn bitxor(self, rhs: Self) -> Self {
self.symmetric_difference(rhs)
}
}
impl std::ops::BitXorAssign for PipelineStageAccessFlags {
#[inline]
fn bitxor_assign(&mut self, rhs: Self) {
*self = self.symmetric_difference(rhs);
}
}
impl std::ops::Sub for PipelineStageAccessFlags {
type Output = Self;
#[inline]
fn sub(self, rhs: Self) -> Self {
self.difference(rhs)
}
}
impl std::ops::SubAssign for PipelineStageAccessFlags {
#[inline]
fn sub_assign(&mut self, rhs: Self) {
*self = self.difference(rhs);
}
}
impl From<PipelineStageAccess> for PipelineStageAccessFlags {
#[inline]
fn from(val: PipelineStageAccess) -> Self {
debug_assert!(val != PipelineStageAccess::__MAX_VALUE__); Self(1u128 << val as u8)
}
}
impl From<PipelineStageAccessFlags> for PipelineStages {
#[inline]
fn from(val: PipelineStageAccessFlags) -> Self {
let mut result = PipelineStages::empty();
$(
if val.intersects(PipelineStageAccessFlags::$val) {
result |= PipelineStages::$stage;
}
)*
result
}
}
impl From<PipelineStageAccessFlags> for AccessFlags {
#[inline]
fn from(val: PipelineStageAccessFlags) -> Self {
let mut result = AccessFlags::empty();
$(
if val.intersects(PipelineStageAccessFlags::$val) {
result |= AccessFlags::$access;
}
)*
result
}
}
};
}
pipeline_stage_access! {
DrawIndirect_IndirectCommandRead, DRAW_INDIRECT, INDIRECT_COMMAND_READ;
DrawIndirect_TransformFeedbackCounterRead, DRAW_INDIRECT, TRANSFORM_FEEDBACK_COUNTER_READ;
VertexShader_UniformRead, VERTEX_SHADER, UNIFORM_READ;
VertexShader_ShaderSampledRead, VERTEX_SHADER, SHADER_SAMPLED_READ;
VertexShader_ShaderStorageRead, VERTEX_SHADER, SHADER_STORAGE_READ;
VertexShader_ShaderStorageWrite, VERTEX_SHADER, SHADER_STORAGE_WRITE;
VertexShader_AccelerationStructureRead, VERTEX_SHADER, ACCELERATION_STRUCTURE_READ;
TessellationControlShader_UniformRead, TESSELLATION_CONTROL_SHADER, UNIFORM_READ;
TessellationControlShader_ShaderSampledRead, TESSELLATION_CONTROL_SHADER, SHADER_SAMPLED_READ;
TessellationControlShader_ShaderStorageRead, TESSELLATION_CONTROL_SHADER, SHADER_STORAGE_READ;
TessellationControlShader_ShaderStorageWrite, TESSELLATION_CONTROL_SHADER, SHADER_STORAGE_WRITE;
TessellationControlShader_AccelerationStructureRead, TESSELLATION_CONTROL_SHADER, ACCELERATION_STRUCTURE_READ;
TessellationEvaluationShader_UniformRead, TESSELLATION_EVALUATION_SHADER, UNIFORM_READ;
TessellationEvaluationShader_ShaderSampledRead, TESSELLATION_EVALUATION_SHADER, SHADER_SAMPLED_READ;
TessellationEvaluationShader_ShaderStorageRead, TESSELLATION_EVALUATION_SHADER, SHADER_STORAGE_READ;
TessellationEvaluationShader_ShaderStorageWrite, TESSELLATION_EVALUATION_SHADER, SHADER_STORAGE_WRITE;
TessellationEvaluationShader_AccelerationStructureRead, TESSELLATION_EVALUATION_SHADER, ACCELERATION_STRUCTURE_READ;
GeometryShader_UniformRead, GEOMETRY_SHADER, UNIFORM_READ;
GeometryShader_ShaderSampledRead, GEOMETRY_SHADER, SHADER_SAMPLED_READ;
GeometryShader_ShaderStorageRead, GEOMETRY_SHADER, SHADER_STORAGE_READ;
GeometryShader_ShaderStorageWrite, GEOMETRY_SHADER, SHADER_STORAGE_WRITE;
GeometryShader_AccelerationStructureRead, GEOMETRY_SHADER, ACCELERATION_STRUCTURE_READ;
FragmentShader_UniformRead, FRAGMENT_SHADER, UNIFORM_READ;
FragmentShader_InputAttachmentRead, FRAGMENT_SHADER, INPUT_ATTACHMENT_READ;
FragmentShader_ShaderSampledRead, FRAGMENT_SHADER, SHADER_SAMPLED_READ;
FragmentShader_ShaderStorageRead, FRAGMENT_SHADER, SHADER_STORAGE_READ;
FragmentShader_ShaderStorageWrite, FRAGMENT_SHADER, SHADER_STORAGE_WRITE;
FragmentShader_AccelerationStructureRead, FRAGMENT_SHADER, ACCELERATION_STRUCTURE_READ;
EarlyFragmentTests_DepthStencilAttachmentRead, EARLY_FRAGMENT_TESTS, DEPTH_STENCIL_ATTACHMENT_READ;
EarlyFragmentTests_DepthStencilAttachmentWrite, EARLY_FRAGMENT_TESTS, DEPTH_STENCIL_ATTACHMENT_WRITE;
LateFragmentTests_DepthStencilAttachmentRead, LATE_FRAGMENT_TESTS, DEPTH_STENCIL_ATTACHMENT_READ;
LateFragmentTests_DepthStencilAttachmentWrite, LATE_FRAGMENT_TESTS, DEPTH_STENCIL_ATTACHMENT_WRITE;
ColorAttachmentOutput_ColorAttachmentRead, COLOR_ATTACHMENT_OUTPUT, COLOR_ATTACHMENT_READ;
ColorAttachmentOutput_ColorAttachmentWrite, COLOR_ATTACHMENT_OUTPUT, COLOR_ATTACHMENT_WRITE;
ColorAttachmentOutput_ColorAttachmentReadNoncoherent, COLOR_ATTACHMENT_OUTPUT, COLOR_ATTACHMENT_READ_NONCOHERENT;
ComputeShader_UniformRead, COMPUTE_SHADER, UNIFORM_READ;
ComputeShader_ShaderSampledRead, COMPUTE_SHADER, SHADER_SAMPLED_READ;
ComputeShader_ShaderStorageRead, COMPUTE_SHADER, SHADER_STORAGE_READ;
ComputeShader_ShaderStorageWrite, COMPUTE_SHADER, SHADER_STORAGE_WRITE;
ComputeShader_AccelerationStructureRead, COMPUTE_SHADER, ACCELERATION_STRUCTURE_READ;
Host_HostRead, HOST, HOST_READ;
Host_HostWrite, HOST, HOST_WRITE;
Copy_TransferRead, COPY, TRANSFER_READ;
Copy_TransferWrite, COPY, TRANSFER_WRITE;
Resolve_TransferRead, RESOLVE, TRANSFER_READ;
Resolve_TransferWrite, RESOLVE, TRANSFER_WRITE;
Blit_TransferRead, BLIT, TRANSFER_READ;
Blit_TransferWrite, BLIT, TRANSFER_WRITE;
Clear_TransferWrite, CLEAR, TRANSFER_WRITE;
IndexInput_IndexRead, INDEX_INPUT, INDEX_READ;
VertexAttributeInput_VertexAttributeRead, VERTEX_ATTRIBUTE_INPUT, VERTEX_ATTRIBUTE_READ;
VideoDecode_VideoDecodeRead, VIDEO_DECODE, VIDEO_DECODE_READ;
VideoDecode_VideoDecodeWrite, VIDEO_DECODE, VIDEO_DECODE_WRITE;
VideoEncode_VideoEncodeRead, VIDEO_ENCODE, VIDEO_ENCODE_READ;
VideoEncode_VideoEncodeWrite, VIDEO_ENCODE, VIDEO_ENCODE_WRITE;
TransformFeedback_TransformFeedbackWrite, TRANSFORM_FEEDBACK, TRANSFORM_FEEDBACK_WRITE;
TransformFeedback_TransformFeedbackCounterRead, TRANSFORM_FEEDBACK, TRANSFORM_FEEDBACK_COUNTER_READ;
TransformFeedback_TransformFeedbackCounterWrite, TRANSFORM_FEEDBACK, TRANSFORM_FEEDBACK_COUNTER_WRITE;
ConditionalRendering_ConditionalRenderingRead, CONDITIONAL_RENDERING, CONDITIONAL_RENDERING_READ;
AccelerationStructureBuild_IndirectCommandRead, ACCELERATION_STRUCTURE_BUILD, INDIRECT_COMMAND_READ;
AccelerationStructureBuild_UniformRead, ACCELERATION_STRUCTURE_BUILD, UNIFORM_READ;
AccelerationStructureBuild_TransferRead, ACCELERATION_STRUCTURE_BUILD, TRANSFER_READ;
AccelerationStructureBuild_TransferWrite, ACCELERATION_STRUCTURE_BUILD, TRANSFER_WRITE;
AccelerationStructureBuild_ShaderSampledRead, ACCELERATION_STRUCTURE_BUILD, SHADER_SAMPLED_READ;
AccelerationStructureBuild_ShaderStorageRead, ACCELERATION_STRUCTURE_BUILD, SHADER_STORAGE_READ;
AccelerationStructureBuild_AccelerationStructureRead, ACCELERATION_STRUCTURE_BUILD, ACCELERATION_STRUCTURE_READ;
AccelerationStructureBuild_AccelerationStructureWrite, ACCELERATION_STRUCTURE_BUILD, ACCELERATION_STRUCTURE_WRITE;
AccelerationStructureBuild_MicromapRead, ACCELERATION_STRUCTURE_BUILD, MICROMAP_READ;
RayTracingShader_UniformRead, RAY_TRACING_SHADER, UNIFORM_READ;
RayTracingShader_ShaderSampledRead, RAY_TRACING_SHADER, SHADER_SAMPLED_READ;
RayTracingShader_ShaderStorageRead, RAY_TRACING_SHADER, SHADER_STORAGE_READ;
RayTracingShader_ShaderStorageWrite, RAY_TRACING_SHADER, SHADER_STORAGE_WRITE;
RayTracingShader_AccelerationStructureRead, RAY_TRACING_SHADER, ACCELERATION_STRUCTURE_READ;
RayTracingShader_ShaderBindingTableRead, RAY_TRACING_SHADER, SHADER_BINDING_TABLE_READ;
FragmentDensityProcess_FragmentDensityMapRead, FRAGMENT_DENSITY_PROCESS, FRAGMENT_DENSITY_MAP_READ;
FragmentShadingRateAttachment_FragmentShadingRateAttachmentRead, FRAGMENT_SHADING_RATE_ATTACHMENT, FRAGMENT_SHADING_RATE_ATTACHMENT_READ;
CommandPreprocess_CommandPreprocessRead, COMMAND_PREPROCESS, COMMAND_PREPROCESS_READ;
CommandPreprocess_CommandPreprocessWrite, COMMAND_PREPROCESS, COMMAND_PREPROCESS_WRITE;
TaskShader_UniformRead, TASK_SHADER, UNIFORM_READ;
TaskShader_ShaderSampledRead, TASK_SHADER, SHADER_SAMPLED_READ;
TaskShader_ShaderStorageRead, TASK_SHADER, SHADER_STORAGE_READ;
TaskShader_ShaderStorageWrite, TASK_SHADER, SHADER_STORAGE_WRITE;
TaskShader_AccelerationStructureRead, TASK_SHADER, ACCELERATION_STRUCTURE_READ;
MeshShader_UniformRead, MESH_SHADER, UNIFORM_READ;
MeshShader_ShaderSampledRead, MESH_SHADER, SHADER_SAMPLED_READ;
MeshShader_ShaderStorageRead, MESH_SHADER, SHADER_STORAGE_READ;
MeshShader_ShaderStorageWrite, MESH_SHADER, SHADER_STORAGE_WRITE;
MeshShader_AccelerationStructureRead, MESH_SHADER, ACCELERATION_STRUCTURE_READ;
SubpassShading_InputAttachmentRead, SUBPASS_SHADING, INPUT_ATTACHMENT_READ;
InvocationMask_InvocationMaskRead, INVOCATION_MASK, INVOCATION_MASK_READ;
AccelerationStructureCopy_AccelerationStructureRead, ACCELERATION_STRUCTURE_COPY, ACCELERATION_STRUCTURE_READ;
AccelerationStructureCopy_AccelerationStructureWrite, ACCELERATION_STRUCTURE_COPY, ACCELERATION_STRUCTURE_WRITE;
AccelerationStructureCopy_TransferRead, ACCELERATION_STRUCTURE_COPY, TRANSFER_READ;
AccelerationStructureCopy_TransferWrite, ACCELERATION_STRUCTURE_COPY, TRANSFER_WRITE;
OpticalFlow_OpticalFlowRead, OPTICAL_FLOW, OPTICAL_FLOW_READ;
OpticalFlow_OpticalFlowWrite, OPTICAL_FLOW, OPTICAL_FLOW_WRITE;
MicromapBuild_MicromapRead, MICROMAP_BUILD, MICROMAP_READ;
MicromapBuild_MicromapWrite, MICROMAP_BUILD, MICROMAP_WRITE;
}
impl PipelineStageAccess {
pub(crate) fn iter_descriptor_stages(
descriptor_type: DescriptorType,
stages_read: ShaderStages,
stages_write: ShaderStages,
) -> impl Iterator<Item = Self> + 'static {
static MAP_READ: Lazy<
HashMap<DescriptorType, HashMap<PipelineStage, PipelineStageAccess>>,
> = Lazy::new(|| {
let uniform_read = [
DescriptorType::UniformBuffer,
DescriptorType::UniformBufferDynamic,
]
.into_iter()
.map(|descriptor_type| {
(
descriptor_type,
[
(
PipelineStage::VertexShader,
PipelineStageAccess::VertexShader_UniformRead,
),
(
PipelineStage::TessellationControlShader,
PipelineStageAccess::TessellationControlShader_UniformRead,
),
(
PipelineStage::TessellationEvaluationShader,
PipelineStageAccess::TessellationControlShader_UniformRead,
),
(
PipelineStage::GeometryShader,
PipelineStageAccess::GeometryShader_UniformRead,
),
(
PipelineStage::FragmentShader,
PipelineStageAccess::FragmentShader_UniformRead,
),
(
PipelineStage::ComputeShader,
PipelineStageAccess::ComputeShader_UniformRead,
),
(
PipelineStage::RayTracingShader,
PipelineStageAccess::RayTracingShader_UniformRead,
),
(
PipelineStage::TaskShader,
PipelineStageAccess::TaskShader_UniformRead,
),
(
PipelineStage::MeshShader,
PipelineStageAccess::MeshShader_UniformRead,
),
]
.into_iter()
.collect(),
)
});
let shader_sampled_read = [
DescriptorType::CombinedImageSampler,
DescriptorType::SampledImage,
DescriptorType::UniformTexelBuffer,
]
.into_iter()
.map(|descriptor_type| {
(
descriptor_type,
[
(
PipelineStage::VertexShader,
PipelineStageAccess::VertexShader_ShaderSampledRead,
),
(
PipelineStage::TessellationControlShader,
PipelineStageAccess::TessellationControlShader_ShaderSampledRead,
),
(
PipelineStage::TessellationEvaluationShader,
PipelineStageAccess::TessellationControlShader_ShaderSampledRead,
),
(
PipelineStage::GeometryShader,
PipelineStageAccess::GeometryShader_ShaderSampledRead,
),
(
PipelineStage::FragmentShader,
PipelineStageAccess::FragmentShader_ShaderSampledRead,
),
(
PipelineStage::ComputeShader,
PipelineStageAccess::ComputeShader_ShaderSampledRead,
),
(
PipelineStage::RayTracingShader,
PipelineStageAccess::RayTracingShader_ShaderSampledRead,
),
(
PipelineStage::TaskShader,
PipelineStageAccess::TaskShader_ShaderSampledRead,
),
(
PipelineStage::MeshShader,
PipelineStageAccess::MeshShader_ShaderSampledRead,
),
]
.into_iter()
.collect(),
)
});
let shader_storage_read = [
DescriptorType::StorageImage,
DescriptorType::StorageTexelBuffer,
DescriptorType::StorageBuffer,
DescriptorType::StorageBufferDynamic,
]
.into_iter()
.map(|descriptor_type| {
(
descriptor_type,
[
(
PipelineStage::VertexShader,
PipelineStageAccess::VertexShader_ShaderStorageRead,
),
(
PipelineStage::TessellationControlShader,
PipelineStageAccess::TessellationControlShader_ShaderStorageRead,
),
(
PipelineStage::TessellationEvaluationShader,
PipelineStageAccess::TessellationControlShader_ShaderStorageRead,
),
(
PipelineStage::GeometryShader,
PipelineStageAccess::GeometryShader_ShaderStorageRead,
),
(
PipelineStage::FragmentShader,
PipelineStageAccess::FragmentShader_ShaderStorageRead,
),
(
PipelineStage::ComputeShader,
PipelineStageAccess::ComputeShader_ShaderStorageRead,
),
(
PipelineStage::RayTracingShader,
PipelineStageAccess::RayTracingShader_ShaderStorageRead,
),
(
PipelineStage::TaskShader,
PipelineStageAccess::TaskShader_ShaderStorageRead,
),
(
PipelineStage::MeshShader,
PipelineStageAccess::MeshShader_ShaderStorageRead,
),
]
.into_iter()
.collect(),
)
});
let input_attachment_read =
[DescriptorType::InputAttachment]
.into_iter()
.map(|descriptor_type| {
(
descriptor_type,
[(
PipelineStage::FragmentShader,
PipelineStageAccess::FragmentShader_InputAttachmentRead,
)]
.into_iter()
.collect(),
)
});
uniform_read
.chain(shader_sampled_read)
.chain(shader_storage_read)
.chain(input_attachment_read)
.collect()
});
static MAP_WRITE: Lazy<
HashMap<DescriptorType, HashMap<PipelineStage, PipelineStageAccess>>,
> = Lazy::new(|| {
let shader_storage_write = [
DescriptorType::StorageImage,
DescriptorType::StorageTexelBuffer,
DescriptorType::StorageBuffer,
DescriptorType::StorageBufferDynamic,
]
.into_iter()
.map(|descriptor_type| {
(
descriptor_type,
[
(
PipelineStage::VertexShader,
PipelineStageAccess::VertexShader_ShaderStorageWrite,
),
(
PipelineStage::TessellationControlShader,
PipelineStageAccess::TessellationControlShader_ShaderStorageWrite,
),
(
PipelineStage::TessellationEvaluationShader,
PipelineStageAccess::TessellationControlShader_ShaderStorageWrite,
),
(
PipelineStage::GeometryShader,
PipelineStageAccess::GeometryShader_ShaderStorageWrite,
),
(
PipelineStage::FragmentShader,
PipelineStageAccess::FragmentShader_ShaderStorageWrite,
),
(
PipelineStage::ComputeShader,
PipelineStageAccess::ComputeShader_ShaderStorageWrite,
),
(
PipelineStage::RayTracingShader,
PipelineStageAccess::RayTracingShader_ShaderStorageWrite,
),
(
PipelineStage::TaskShader,
PipelineStageAccess::TaskShader_ShaderStorageWrite,
),
(
PipelineStage::MeshShader,
PipelineStageAccess::MeshShader_ShaderStorageWrite,
),
]
.into_iter()
.collect(),
)
});
shader_storage_write.collect()
});
[
(stages_read, &*MAP_READ, "read"),
(stages_write, &*MAP_WRITE, "write"),
]
.into_iter()
.filter(|(stages, _, _)| !stages.is_empty())
.flat_map(move |(stages, descriptor_map, access)| {
let stages_map = descriptor_map.get(&descriptor_type).unwrap_or_else(|| {
panic!(
"DescriptorType::{:?} does not {} memory",
descriptor_type, access,
)
});
PipelineStages::from(stages).into_iter().map(move |stage| {
*stages_map.get(&stage).unwrap_or_else(|| {
panic!(
"DescriptorType::{:?} does not {} memory in PipelineStage::{:?}",
descriptor_type, access, stage,
)
})
})
})
}
}
impl PipelineStageAccessFlags {
#[inline]
pub(crate) fn contains_write(self) -> bool {
self.intersects(
PipelineStageAccessFlags::VertexShader_ShaderStorageWrite
| PipelineStageAccessFlags::TessellationControlShader_ShaderStorageWrite
| PipelineStageAccessFlags::TessellationEvaluationShader_ShaderStorageWrite
| PipelineStageAccessFlags::GeometryShader_ShaderStorageWrite
| PipelineStageAccessFlags::FragmentShader_ShaderStorageWrite
| PipelineStageAccessFlags::EarlyFragmentTests_DepthStencilAttachmentWrite
| PipelineStageAccessFlags::LateFragmentTests_DepthStencilAttachmentWrite
| PipelineStageAccessFlags::ColorAttachmentOutput_ColorAttachmentWrite
| PipelineStageAccessFlags::ComputeShader_ShaderStorageWrite
| PipelineStageAccessFlags::Host_HostWrite
| PipelineStageAccessFlags::Copy_TransferWrite
| PipelineStageAccessFlags::Resolve_TransferWrite
| PipelineStageAccessFlags::Blit_TransferWrite
| PipelineStageAccessFlags::Clear_TransferWrite
| PipelineStageAccessFlags::VideoDecode_VideoDecodeWrite
| PipelineStageAccessFlags::VideoEncode_VideoEncodeWrite
| PipelineStageAccessFlags::TransformFeedback_TransformFeedbackWrite
| PipelineStageAccessFlags::TransformFeedback_TransformFeedbackCounterWrite
| PipelineStageAccessFlags::AccelerationStructureBuild_TransferWrite
| PipelineStageAccessFlags::AccelerationStructureBuild_AccelerationStructureWrite
| PipelineStageAccessFlags::RayTracingShader_ShaderStorageWrite
| PipelineStageAccessFlags::CommandPreprocess_CommandPreprocessWrite
| PipelineStageAccessFlags::TaskShader_ShaderStorageWrite
| PipelineStageAccessFlags::MeshShader_ShaderStorageWrite
| PipelineStageAccessFlags::AccelerationStructureCopy_AccelerationStructureWrite
| PipelineStageAccessFlags::AccelerationStructureCopy_TransferWrite
| PipelineStageAccessFlags::OpticalFlow_OpticalFlowWrite
| PipelineStageAccessFlags::MicromapBuild_MicromapWrite,
)
}
}
#[derive(Clone, Debug)]
pub struct DependencyInfo {
pub dependency_flags: DependencyFlags,
pub memory_barriers: SmallVec<[MemoryBarrier; 2]>,
pub buffer_memory_barriers: SmallVec<[BufferMemoryBarrier; 8]>,
pub image_memory_barriers: SmallVec<[ImageMemoryBarrier; 8]>,
pub _ne: crate::NonExhaustive,
}
impl DependencyInfo {
#[inline]
pub fn is_empty(&self) -> bool {
self.memory_barriers.is_empty()
&& self.buffer_memory_barriers.is_empty()
&& self.image_memory_barriers.is_empty()
}
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
dependency_flags,
ref memory_barriers,
ref buffer_memory_barriers,
ref image_memory_barriers,
_ne: _,
} = self;
dependency_flags.validate_device(device).map_err(|err| {
err.add_context("dependency_flags")
.set_vuids(&["VUID-VkDependencyInfo-dependencyFlags-parameter"])
})?;
for (barrier_index, memory_barrier) in memory_barriers.iter().enumerate() {
memory_barrier
.validate(device)
.map_err(|err| err.add_context(format!("memory_barriers[{}]", barrier_index)))?;
}
for (barrier_index, buffer_memory_barrier) in buffer_memory_barriers.iter().enumerate() {
buffer_memory_barrier.validate(device).map_err(|err| {
err.add_context(format!("buffer_memory_barriers[{}]", barrier_index))
})?;
}
for (barrier_index, image_memory_barrier) in image_memory_barriers.iter().enumerate() {
image_memory_barrier.validate(device).map_err(|err| {
err.add_context(format!("image_memory_barriers[{}]", barrier_index))
})?;
}
Ok(())
}
}
impl Default for DependencyInfo {
#[inline]
fn default() -> Self {
Self {
dependency_flags: DependencyFlags::empty(),
memory_barriers: SmallVec::new(),
buffer_memory_barriers: SmallVec::new(),
image_memory_barriers: SmallVec::new(),
_ne: crate::NonExhaustive(()),
}
}
}
vulkan_bitflags! {
#[non_exhaustive]
DependencyFlags = DependencyFlags(u32);
BY_REGION = BY_REGION,
DEVICE_GROUP = DEVICE_GROUP
RequiresOneOf([
RequiresAllOf([APIVersion(V1_1)]),
RequiresAllOf([DeviceExtension(khr_device_group)]),
]),
VIEW_LOCAL = VIEW_LOCAL
RequiresOneOf([
RequiresAllOf([APIVersion(V1_1)]),
RequiresAllOf([DeviceExtension(khr_multiview)]),
]),
}
#[derive(Clone, Debug)]
pub struct MemoryBarrier {
pub src_stages: PipelineStages,
pub src_access: AccessFlags,
pub dst_stages: PipelineStages,
pub dst_access: AccessFlags,
pub _ne: crate::NonExhaustive,
}
impl Default for MemoryBarrier {
#[inline]
fn default() -> Self {
Self {
src_stages: PipelineStages::empty(),
src_access: AccessFlags::empty(),
dst_stages: PipelineStages::empty(),
dst_access: AccessFlags::empty(),
_ne: crate::NonExhaustive(()),
}
}
}
impl MemoryBarrier {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
src_stages,
src_access,
dst_stages,
dst_access,
_ne: _,
} = self;
src_stages.validate_device(device).map_err(|err| {
err.add_context("src_stages")
.set_vuids(&["VUID-VkMemoryBarrier2-srcStageMask-parameter"])
})?;
dst_stages.validate_device(device).map_err(|err| {
err.add_context("dst_stages")
.set_vuids(&["VUID-VkMemoryBarrier2-dstStageMask-parameter"])
})?;
src_access.validate_device(device).map_err(|err| {
err.add_context("src_access")
.set_vuids(&["VUID-VkMemoryBarrier2-srcAccessMask-parameter"])
})?;
dst_access.validate_device(device).map_err(|err| {
err.add_context("dst_access")
.set_vuids(&["VUID-VkMemoryBarrier2-dstAccessMask-parameter"])
})?;
if !device.enabled_features().synchronization2 {
if src_stages.contains_flags2() {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains flags from `VkPipelineStageFlagBits2`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"synchronization2",
)])]),
..Default::default()
}));
}
if dst_stages.contains_flags2() {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains flags from `VkPipelineStageFlagBits2`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"synchronization2",
)])]),
..Default::default()
}));
}
if src_access.contains_flags2() {
return Err(Box::new(ValidationError {
context: "src_access".into(),
problem: "contains flags from `VkAccessFlagBits2`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"synchronization2",
)])]),
..Default::default()
}));
}
if dst_access.contains_flags2() {
return Err(Box::new(ValidationError {
context: "dst_access".into(),
problem: "contains flags from `VkAccessFlagBits2`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"synchronization2",
)])]),
..Default::default()
}));
}
}
if !device.enabled_features().geometry_shader {
if src_stages.intersects(PipelineStages::GEOMETRY_SHADER) {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::GEOMETRY_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"geometry_shader",
)])]),
vuids: &["VUID-VkMemoryBarrier2-srcStageMask-03929"],
}));
}
if dst_stages.intersects(PipelineStages::GEOMETRY_SHADER) {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::GEOMETRY_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"geometry_shader",
)])]),
vuids: &["VUID-VkMemoryBarrier2-dstStageMask-03929"],
}));
}
}
if !device.enabled_features().tessellation_shader {
if src_stages.intersects(
PipelineStages::TESSELLATION_CONTROL_SHADER
| PipelineStages::TESSELLATION_EVALUATION_SHADER,
) {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::TESSELLATION_CONTROL_SHADER` or \
`PipelineStages::TESSELLATION_EVALUATION_SHADER`"
.into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"tessellation_shader",
)])]),
vuids: &["VUID-VkMemoryBarrier2-srcStageMask-03930"],
}));
}
if dst_stages.intersects(
PipelineStages::TESSELLATION_CONTROL_SHADER
| PipelineStages::TESSELLATION_EVALUATION_SHADER,
) {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::TESSELLATION_CONTROL_SHADER` or \
`PipelineStages::TESSELLATION_EVALUATION_SHADER`"
.into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"tessellation_shader",
)])]),
vuids: &["VUID-VkMemoryBarrier2-dstStageMask-03930"],
}));
}
}
if !device.enabled_features().conditional_rendering {
if src_stages.intersects(PipelineStages::CONDITIONAL_RENDERING) {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::CONDITIONAL_RENDERING`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"conditional_rendering",
)])]),
vuids: &["VUID-VkMemoryBarrier2-srcStageMask-03931"],
}));
}
if dst_stages.intersects(PipelineStages::CONDITIONAL_RENDERING) {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::CONDITIONAL_RENDERING`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"conditional_rendering",
)])]),
vuids: &["VUID-VkMemoryBarrier2-dstStageMask-03931"],
}));
}
}
if !device.enabled_features().fragment_density_map {
if src_stages.intersects(PipelineStages::FRAGMENT_DENSITY_PROCESS) {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::FRAGMENT_DENSITY_PROCESS`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"fragment_density_map",
)])]),
vuids: &["VUID-VkMemoryBarrier2-srcStageMask-03932"],
}));
}
if dst_stages.intersects(PipelineStages::FRAGMENT_DENSITY_PROCESS) {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::FRAGMENT_DENSITY_PROCESS`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"fragment_density_map",
)])]),
vuids: &["VUID-VkMemoryBarrier2-dstStageMask-03932"],
}));
}
}
if !device.enabled_features().transform_feedback {
if src_stages.intersects(PipelineStages::TRANSFORM_FEEDBACK) {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::TRANSFORM_FEEDBACK`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"transform_feedback",
)])]),
vuids: &["VUID-VkMemoryBarrier2-srcStageMask-03933"],
}));
}
if dst_stages.intersects(PipelineStages::TRANSFORM_FEEDBACK) {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::TRANSFORM_FEEDBACK`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"transform_feedback",
)])]),
vuids: &["VUID-VkMemoryBarrier2-dstStageMask-03933"],
}));
}
}
if !device.enabled_features().mesh_shader {
if src_stages.intersects(PipelineStages::MESH_SHADER) {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::MESH_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"mesh_shader",
)])]),
vuids: &["VUID-VkMemoryBarrier2-srcStageMask-03934"],
}));
}
if dst_stages.intersects(PipelineStages::MESH_SHADER) {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::MESH_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"mesh_shader",
)])]),
vuids: &["VUID-VkMemoryBarrier2-dstStageMask-03934"],
}));
}
}
if !device.enabled_features().task_shader {
if src_stages.intersects(PipelineStages::TASK_SHADER) {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::TASK_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"task_shader",
)])]),
vuids: &["VUID-VkMemoryBarrier2-srcStageMask-03935"],
}));
}
if dst_stages.intersects(PipelineStages::TASK_SHADER) {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::TASK_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"task_shader",
)])]),
vuids: &["VUID-VkMemoryBarrier2-dstStageMask-03935"],
}));
}
}
if !(device.enabled_features().attachment_fragment_shading_rate
|| device.enabled_features().shading_rate_image)
{
if src_stages.intersects(PipelineStages::FRAGMENT_SHADING_RATE_ATTACHMENT) {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::FRAGMENT_SHADING_RATE_ATTACHMENT`".into(),
requires_one_of: RequiresOneOf(&[
RequiresAllOf(&[Requires::Feature("attachment_fragment_shading_rate")]),
RequiresAllOf(&[Requires::Feature("shading_rate_image")]),
]),
vuids: &["VUID-VkMemoryBarrier2-shadingRateImage-07316"],
}));
}
if dst_stages.intersects(PipelineStages::FRAGMENT_SHADING_RATE_ATTACHMENT) {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::FRAGMENT_SHADING_RATE_ATTACHMENT`".into(),
requires_one_of: RequiresOneOf(&[
RequiresAllOf(&[Requires::Feature("attachment_fragment_shading_rate")]),
RequiresAllOf(&[Requires::Feature("shading_rate_image")]),
]),
vuids: &["VUID-VkMemoryBarrier2-shadingRateImage-07316"],
}));
}
}
if !device.enabled_features().subpass_shading {
if src_stages.intersects(PipelineStages::SUBPASS_SHADING) {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::SUBPASS_SHADING`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"subpass_shading",
)])]),
vuids: &["VUID-VkMemoryBarrier2-srcStageMask-04957"],
}));
}
if dst_stages.intersects(PipelineStages::SUBPASS_SHADING) {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::SUBPASS_SHADING`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"subpass_shading",
)])]),
vuids: &["VUID-VkMemoryBarrier2-dstStageMask-04957"],
}));
}
}
if !device.enabled_features().invocation_mask {
if src_stages.intersects(PipelineStages::INVOCATION_MASK) {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::INVOCATION_MASK`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"invocation_mask",
)])]),
vuids: &["VUID-VkMemoryBarrier2-srcStageMask-04995"],
}));
}
if dst_stages.intersects(PipelineStages::INVOCATION_MASK) {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::INVOCATION_MASK`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"invocation_mask",
)])]),
vuids: &["VUID-VkMemoryBarrier2-dstStageMask-04995"],
}));
}
}
if !(device.enabled_extensions().nv_ray_tracing
|| device.enabled_features().ray_tracing_pipeline)
{
if src_stages.intersects(PipelineStages::RAY_TRACING_SHADER) {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::RAY_TRACING_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"ray_tracing_pipeline",
)])]),
vuids: &["VUID-VkMemoryBarrier2-srcStageMask-07946"],
}));
}
if dst_stages.intersects(PipelineStages::RAY_TRACING_SHADER) {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::RAY_TRACING_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"ray_tracing_pipeline",
)])]),
vuids: &["VUID-VkMemoryBarrier2-dstStageMask-07946"],
}));
}
}
if !AccessFlags::from(src_stages).contains(src_access) {
return Err(Box::new(ValidationError {
problem: "`src_access` contains one or more access types that are not performed \
by any stage in `src_stages`"
.into(),
vuids: &[
"VUID-VkMemoryBarrier2-srcAccessMask-03900",
"VUID-VkMemoryBarrier2-srcAccessMask-03901",
"VUID-VkMemoryBarrier2-srcAccessMask-03902",
"VUID-VkMemoryBarrier2-srcAccessMask-03903",
"VUID-VkMemoryBarrier2-srcAccessMask-03904",
"VUID-VkMemoryBarrier2-srcAccessMask-03905",
"VUID-VkMemoryBarrier2-srcAccessMask-03906",
"VUID-VkMemoryBarrier2-srcAccessMask-03907",
"VUID-VkMemoryBarrier2-srcAccessMask-07454",
"VUID-VkMemoryBarrier2-srcAccessMask-03909",
"VUID-VkMemoryBarrier2-srcAccessMask-03910",
"VUID-VkMemoryBarrier2-srcAccessMask-03911",
"VUID-VkMemoryBarrier2-srcAccessMask-03912",
"VUID-VkMemoryBarrier2-srcAccessMask-03913",
"VUID-VkMemoryBarrier2-srcAccessMask-03914",
"VUID-VkMemoryBarrier2-srcAccessMask-03915",
"VUID-VkMemoryBarrier2-srcAccessMask-03916",
"VUID-VkMemoryBarrier2-srcAccessMask-03917",
"VUID-VkMemoryBarrier2-srcAccessMask-03918",
"VUID-VkMemoryBarrier2-srcAccessMask-03919",
"VUID-VkMemoryBarrier2-srcAccessMask-03920",
"VUID-VkMemoryBarrier2-srcAccessMask-04747",
"VUID-VkMemoryBarrier2-srcAccessMask-03922",
"VUID-VkMemoryBarrier2-srcAccessMask-03923",
"VUID-VkMemoryBarrier2-srcAccessMask-04994",
"VUID-VkMemoryBarrier2-srcAccessMask-03924",
"VUID-VkMemoryBarrier2-srcAccessMask-03925",
"VUID-VkMemoryBarrier2-srcAccessMask-03926",
"VUID-VkMemoryBarrier2-srcAccessMask-03927",
"VUID-VkMemoryBarrier2-srcAccessMask-03928",
"VUID-VkMemoryBarrier2-srcAccessMask-06256",
"VUID-VkMemoryBarrier2-srcAccessMask-07272",
"VUID-VkMemoryBarrier2-srcAccessMask-04858",
"VUID-VkMemoryBarrier2-srcAccessMask-04859",
"VUID-VkMemoryBarrier2-srcAccessMask-04860",
"VUID-VkMemoryBarrier2-srcAccessMask-04861",
"VUID-VkMemoryBarrier2-srcAccessMask-07455",
"VUID-VkMemoryBarrier2-srcAccessMask-07456",
"VUID-VkMemoryBarrier2-srcAccessMask-07457",
"VUID-VkMemoryBarrier2-srcAccessMask-07458",
"VUID-VkMemoryBarrier2-srcAccessMask-08118",
],
..Default::default()
}));
}
if !AccessFlags::from(dst_stages).contains(dst_access) {
return Err(Box::new(ValidationError {
problem: "`dst_access` contains one or more access types that are not performed \
by any stage in `dst_stages`"
.into(),
vuids: &[
"VUID-VkMemoryBarrier2-dstAccessMask-03900",
"VUID-VkMemoryBarrier2-dstAccessMask-03901",
"VUID-VkMemoryBarrier2-dstAccessMask-03902",
"VUID-VkMemoryBarrier2-dstAccessMask-03903",
"VUID-VkMemoryBarrier2-dstAccessMask-03904",
"VUID-VkMemoryBarrier2-dstAccessMask-03905",
"VUID-VkMemoryBarrier2-dstAccessMask-03906",
"VUID-VkMemoryBarrier2-dstAccessMask-03907",
"VUID-VkMemoryBarrier2-dstAccessMask-07454",
"VUID-VkMemoryBarrier2-dstAccessMask-03909",
"VUID-VkMemoryBarrier2-dstAccessMask-03910",
"VUID-VkMemoryBarrier2-dstAccessMask-03911",
"VUID-VkMemoryBarrier2-dstAccessMask-03912",
"VUID-VkMemoryBarrier2-dstAccessMask-03913",
"VUID-VkMemoryBarrier2-dstAccessMask-03914",
"VUID-VkMemoryBarrier2-dstAccessMask-03915",
"VUID-VkMemoryBarrier2-dstAccessMask-03916",
"VUID-VkMemoryBarrier2-dstAccessMask-03917",
"VUID-VkMemoryBarrier2-dstAccessMask-03918",
"VUID-VkMemoryBarrier2-dstAccessMask-03919",
"VUID-VkMemoryBarrier2-dstAccessMask-03920",
"VUID-VkMemoryBarrier2-dstAccessMask-04747",
"VUID-VkMemoryBarrier2-dstAccessMask-03922",
"VUID-VkMemoryBarrier2-dstAccessMask-03923",
"VUID-VkMemoryBarrier2-dstAccessMask-04994",
"VUID-VkMemoryBarrier2-dstAccessMask-03924",
"VUID-VkMemoryBarrier2-dstAccessMask-03925",
"VUID-VkMemoryBarrier2-dstAccessMask-03926",
"VUID-VkMemoryBarrier2-dstAccessMask-03927",
"VUID-VkMemoryBarrier2-dstAccessMask-03928",
"VUID-VkMemoryBarrier2-dstAccessMask-06256",
"VUID-VkMemoryBarrier2-dstAccessMask-07272",
"VUID-VkMemoryBarrier2-dstAccessMask-04858",
"VUID-VkMemoryBarrier2-dstAccessMask-04859",
"VUID-VkMemoryBarrier2-dstAccessMask-04860",
"VUID-VkMemoryBarrier2-dstAccessMask-04861",
"VUID-VkMemoryBarrier2-dstAccessMask-07455",
"VUID-VkMemoryBarrier2-dstAccessMask-07456",
"VUID-VkMemoryBarrier2-dstAccessMask-07457",
"VUID-VkMemoryBarrier2-dstAccessMask-07458",
"VUID-VkMemoryBarrier2-dstAccessMask-08118",
],
..Default::default()
}));
}
Ok(())
}
}
#[derive(Clone, Debug)]
pub struct BufferMemoryBarrier {
pub src_stages: PipelineStages,
pub src_access: AccessFlags,
pub dst_stages: PipelineStages,
pub dst_access: AccessFlags,
pub queue_family_ownership_transfer: Option<QueueFamilyOwnershipTransfer>,
pub buffer: Arc<Buffer>,
pub range: Range<DeviceSize>,
pub _ne: crate::NonExhaustive,
}
impl BufferMemoryBarrier {
#[inline]
pub fn buffer(buffer: Arc<Buffer>) -> Self {
Self {
src_stages: PipelineStages::empty(),
src_access: AccessFlags::empty(),
dst_stages: PipelineStages::empty(),
dst_access: AccessFlags::empty(),
queue_family_ownership_transfer: None,
buffer,
range: 0..0,
_ne: crate::NonExhaustive(()),
}
}
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
src_stages,
src_access,
dst_stages,
dst_access,
ref queue_family_ownership_transfer,
ref buffer,
ref range,
_ne,
} = self;
src_stages.validate_device(device).map_err(|err| {
err.add_context("src_stages")
.set_vuids(&["VUID-VkBufferMemoryBarrier2-srcStageMask-parameter"])
})?;
dst_stages.validate_device(device).map_err(|err| {
err.add_context("dst_stages")
.set_vuids(&["VUID-VkBufferMemoryBarrier2-dstStageMask-parameter"])
})?;
src_access.validate_device(device).map_err(|err| {
err.add_context("src_access")
.set_vuids(&["VUID-VkBufferMemoryBarrier2-srcAccessMask-parameter"])
})?;
dst_access.validate_device(device).map_err(|err| {
err.add_context("dst_access")
.set_vuids(&["VUID-VkBufferMemoryBarrier2-dstAccessMask-parameter"])
})?;
if !device.enabled_features().synchronization2 {
if src_stages.contains_flags2() {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains flags from `VkPipelineStageFlagBits2`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"synchronization2",
)])]),
..Default::default()
}));
}
if dst_stages.contains_flags2() {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains flags from `VkPipelineStageFlagBits2`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"synchronization2",
)])]),
..Default::default()
}));
}
if src_access.contains_flags2() {
return Err(Box::new(ValidationError {
context: "src_access".into(),
problem: "contains flags from `VkAccessFlagBits2`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"synchronization2",
)])]),
..Default::default()
}));
}
if dst_access.contains_flags2() {
return Err(Box::new(ValidationError {
context: "dst_access".into(),
problem: "contains flags from `VkAccessFlagBits2`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"synchronization2",
)])]),
..Default::default()
}));
}
}
if !device.enabled_features().geometry_shader {
if src_stages.intersects(PipelineStages::GEOMETRY_SHADER) {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::GEOMETRY_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"geometry_shader",
)])]),
vuids: &["VUID-VkBufferMemoryBarrier2-srcStageMask-03929"],
}));
}
if dst_stages.intersects(PipelineStages::GEOMETRY_SHADER) {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::GEOMETRY_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"geometry_shader",
)])]),
vuids: &["VUID-VkBufferMemoryBarrier2-dstStageMask-03929"],
}));
}
}
if !device.enabled_features().tessellation_shader {
if src_stages.intersects(
PipelineStages::TESSELLATION_CONTROL_SHADER
| PipelineStages::TESSELLATION_EVALUATION_SHADER,
) {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::TESSELLATION_CONTROL_SHADER` or \
`PipelineStages::TESSELLATION_EVALUATION_SHADER`"
.into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"tessellation_shader",
)])]),
vuids: &["VUID-VkBufferMemoryBarrier2-srcStageMask-03930"],
}));
}
if dst_stages.intersects(
PipelineStages::TESSELLATION_CONTROL_SHADER
| PipelineStages::TESSELLATION_EVALUATION_SHADER,
) {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::TESSELLATION_CONTROL_SHADER` or \
`PipelineStages::TESSELLATION_EVALUATION_SHADER`"
.into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"tessellation_shader",
)])]),
vuids: &["VUID-VkBufferMemoryBarrier2-dstStageMask-03930"],
}));
}
}
if !device.enabled_features().conditional_rendering {
if src_stages.intersects(PipelineStages::CONDITIONAL_RENDERING) {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::CONDITIONAL_RENDERING`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"conditional_rendering",
)])]),
vuids: &["VUID-VkBufferMemoryBarrier2-srcStageMask-03931"],
}));
}
if dst_stages.intersects(PipelineStages::CONDITIONAL_RENDERING) {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::CONDITIONAL_RENDERING`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"conditional_rendering",
)])]),
vuids: &["VUID-VkBufferMemoryBarrier2-dstStageMask-03931"],
}));
}
}
if !device.enabled_features().fragment_density_map {
if src_stages.intersects(PipelineStages::FRAGMENT_DENSITY_PROCESS) {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::FRAGMENT_DENSITY_PROCESS`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"fragment_density_map",
)])]),
vuids: &["VUID-VkBufferMemoryBarrier2-srcStageMask-03932"],
}));
}
if dst_stages.intersects(PipelineStages::FRAGMENT_DENSITY_PROCESS) {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::FRAGMENT_DENSITY_PROCESS`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"fragment_density_map",
)])]),
vuids: &["VUID-VkBufferMemoryBarrier2-dstStageMask-03932"],
}));
}
}
if !device.enabled_features().transform_feedback {
if src_stages.intersects(PipelineStages::TRANSFORM_FEEDBACK) {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::TRANSFORM_FEEDBACK`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"transform_feedback",
)])]),
vuids: &["VUID-VkBufferMemoryBarrier2-srcStageMask-03933"],
}));
}
if dst_stages.intersects(PipelineStages::TRANSFORM_FEEDBACK) {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::TRANSFORM_FEEDBACK`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"transform_feedback",
)])]),
vuids: &["VUID-VkBufferMemoryBarrier2-dstStageMask-03933"],
}));
}
}
if !device.enabled_features().mesh_shader {
if src_stages.intersects(PipelineStages::MESH_SHADER) {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::MESH_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"mesh_shader",
)])]),
vuids: &["VUID-VkBufferMemoryBarrier2-srcStageMask-03934"],
}));
}
if dst_stages.intersects(PipelineStages::MESH_SHADER) {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::MESH_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"mesh_shader",
)])]),
vuids: &["VUID-VkBufferMemoryBarrier2-dstStageMask-03934"],
}));
}
}
if !device.enabled_features().task_shader {
if src_stages.intersects(PipelineStages::TASK_SHADER) {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::TASK_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"task_shader",
)])]),
vuids: &["VUID-VkBufferMemoryBarrier2-srcStageMask-03935"],
}));
}
if dst_stages.intersects(PipelineStages::TASK_SHADER) {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::TASK_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"task_shader",
)])]),
vuids: &["VUID-VkBufferMemoryBarrier2-dstStageMask-03935"],
}));
}
}
if !(device.enabled_features().attachment_fragment_shading_rate
|| device.enabled_features().shading_rate_image)
{
if src_stages.intersects(PipelineStages::FRAGMENT_SHADING_RATE_ATTACHMENT) {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::FRAGMENT_SHADING_RATE_ATTACHMENT`".into(),
requires_one_of: RequiresOneOf(&[
RequiresAllOf(&[Requires::Feature("attachment_fragment_shading_rate")]),
RequiresAllOf(&[Requires::Feature("shading_rate_image")]),
]),
vuids: &["VUID-VkBufferMemoryBarrier2-shadingRateImage-07316"],
}));
}
if dst_stages.intersects(PipelineStages::FRAGMENT_SHADING_RATE_ATTACHMENT) {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::FRAGMENT_SHADING_RATE_ATTACHMENT`".into(),
requires_one_of: RequiresOneOf(&[
RequiresAllOf(&[Requires::Feature("attachment_fragment_shading_rate")]),
RequiresAllOf(&[Requires::Feature("shading_rate_image")]),
]),
vuids: &["VUID-VkBufferMemoryBarrier2-shadingRateImage-07316"],
}));
}
}
if !device.enabled_features().subpass_shading {
if src_stages.intersects(PipelineStages::SUBPASS_SHADING) {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::SUBPASS_SHADING`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"subpass_shading",
)])]),
vuids: &["VUID-VkBufferMemoryBarrier2-srcStageMask-04957"],
}));
}
if dst_stages.intersects(PipelineStages::SUBPASS_SHADING) {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::SUBPASS_SHADING`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"subpass_shading",
)])]),
vuids: &["VUID-VkBufferMemoryBarrier2-dstStageMask-04957"],
}));
}
}
if !device.enabled_features().invocation_mask {
if src_stages.intersects(PipelineStages::INVOCATION_MASK) {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::INVOCATION_MASK`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"invocation_mask",
)])]),
vuids: &["VUID-VkBufferMemoryBarrier2-srcStageMask-04995"],
}));
}
if dst_stages.intersects(PipelineStages::INVOCATION_MASK) {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::INVOCATION_MASK`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"invocation_mask",
)])]),
vuids: &["VUID-VkBufferMemoryBarrier2-dstStageMask-04995"],
}));
}
}
if !(device.enabled_extensions().nv_ray_tracing
|| device.enabled_features().ray_tracing_pipeline)
{
if src_stages.intersects(PipelineStages::RAY_TRACING_SHADER) {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::RAY_TRACING_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"ray_tracing_pipeline",
)])]),
vuids: &["VUID-VkBufferMemoryBarrier2-srcStageMask-07946"],
}));
}
if dst_stages.intersects(PipelineStages::RAY_TRACING_SHADER) {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::RAY_TRACING_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"ray_tracing_pipeline",
)])]),
vuids: &["VUID-VkBufferMemoryBarrier2-dstStageMask-07946"],
}));
}
}
if !AccessFlags::from(src_stages).contains(src_access) {
return Err(Box::new(ValidationError {
problem: "`src_access` contains one or more access types that are not performed \
by any stage in `src_stages`"
.into(),
vuids: &[
"VUID-VkBufferMemoryBarrier2-srcAccessMask-03900",
"VUID-VkBufferMemoryBarrier2-srcAccessMask-03901",
"VUID-VkBufferMemoryBarrier2-srcAccessMask-03902",
"VUID-VkBufferMemoryBarrier2-srcAccessMask-03903",
"VUID-VkBufferMemoryBarrier2-srcAccessMask-03904",
"VUID-VkBufferMemoryBarrier2-srcAccessMask-03905",
"VUID-VkBufferMemoryBarrier2-srcAccessMask-03906",
"VUID-VkBufferMemoryBarrier2-srcAccessMask-03907",
"VUID-VkBufferMemoryBarrier2-srcAccessMask-07454",
"VUID-VkBufferMemoryBarrier2-srcAccessMask-03909",
"VUID-VkBufferMemoryBarrier2-srcAccessMask-03910",
"VUID-VkBufferMemoryBarrier2-srcAccessMask-03911",
"VUID-VkBufferMemoryBarrier2-srcAccessMask-03912",
"VUID-VkBufferMemoryBarrier2-srcAccessMask-03913",
"VUID-VkBufferMemoryBarrier2-srcAccessMask-03914",
"VUID-VkBufferMemoryBarrier2-srcAccessMask-03915",
"VUID-VkBufferMemoryBarrier2-srcAccessMask-03916",
"VUID-VkBufferMemoryBarrier2-srcAccessMask-03917",
"VUID-VkBufferMemoryBarrier2-srcAccessMask-03918",
"VUID-VkBufferMemoryBarrier2-srcAccessMask-03919",
"VUID-VkBufferMemoryBarrier2-srcAccessMask-03920",
"VUID-VkBufferMemoryBarrier2-srcAccessMask-04747",
"VUID-VkBufferMemoryBarrier2-srcAccessMask-03922",
"VUID-VkBufferMemoryBarrier2-srcAccessMask-03923",
"VUID-VkBufferMemoryBarrier2-srcAccessMask-04994",
"VUID-VkBufferMemoryBarrier2-srcAccessMask-03924",
"VUID-VkBufferMemoryBarrier2-srcAccessMask-03925",
"VUID-VkBufferMemoryBarrier2-srcAccessMask-03926",
"VUID-VkBufferMemoryBarrier2-srcAccessMask-03927",
"VUID-VkBufferMemoryBarrier2-srcAccessMask-03928",
"VUID-VkBufferMemoryBarrier2-srcAccessMask-06256",
"VUID-VkBufferMemoryBarrier2-srcAccessMask-07272",
"VUID-VkBufferMemoryBarrier2-srcAccessMask-04858",
"VUID-VkBufferMemoryBarrier2-srcAccessMask-04859",
"VUID-VkBufferMemoryBarrier2-srcAccessMask-04860",
"VUID-VkBufferMemoryBarrier2-srcAccessMask-04861",
"VUID-VkBufferMemoryBarrier2-srcAccessMask-07455",
"VUID-VkBufferMemoryBarrier2-srcAccessMask-07456",
"VUID-VkBufferMemoryBarrier2-srcAccessMask-07457",
"VUID-VkBufferMemoryBarrier2-srcAccessMask-07458",
"VUID-VkBufferMemoryBarrier2-srcAccessMask-08118",
],
..Default::default()
}));
}
if !AccessFlags::from(dst_stages).contains(dst_access) {
return Err(Box::new(ValidationError {
problem: "`dst_access` contains one or more access types that are not performed \
by any stage in `dst_stages`"
.into(),
vuids: &[
"VUID-VkBufferMemoryBarrier2-dstAccessMask-03900",
"VUID-VkBufferMemoryBarrier2-dstAccessMask-03901",
"VUID-VkBufferMemoryBarrier2-dstAccessMask-03902",
"VUID-VkBufferMemoryBarrier2-dstAccessMask-03903",
"VUID-VkBufferMemoryBarrier2-dstAccessMask-03904",
"VUID-VkBufferMemoryBarrier2-dstAccessMask-03905",
"VUID-VkBufferMemoryBarrier2-dstAccessMask-03906",
"VUID-VkBufferMemoryBarrier2-dstAccessMask-03907",
"VUID-VkBufferMemoryBarrier2-dstAccessMask-07454",
"VUID-VkBufferMemoryBarrier2-dstAccessMask-03909",
"VUID-VkBufferMemoryBarrier2-dstAccessMask-03910",
"VUID-VkBufferMemoryBarrier2-dstAccessMask-03911",
"VUID-VkBufferMemoryBarrier2-dstAccessMask-03912",
"VUID-VkBufferMemoryBarrier2-dstAccessMask-03913",
"VUID-VkBufferMemoryBarrier2-dstAccessMask-03914",
"VUID-VkBufferMemoryBarrier2-dstAccessMask-03915",
"VUID-VkBufferMemoryBarrier2-dstAccessMask-03916",
"VUID-VkBufferMemoryBarrier2-dstAccessMask-03917",
"VUID-VkBufferMemoryBarrier2-dstAccessMask-03918",
"VUID-VkBufferMemoryBarrier2-dstAccessMask-03919",
"VUID-VkBufferMemoryBarrier2-dstAccessMask-03920",
"VUID-VkBufferMemoryBarrier2-dstAccessMask-04747",
"VUID-VkBufferMemoryBarrier2-dstAccessMask-03922",
"VUID-VkBufferMemoryBarrier2-dstAccessMask-03923",
"VUID-VkBufferMemoryBarrier2-dstAccessMask-04994",
"VUID-VkBufferMemoryBarrier2-dstAccessMask-03924",
"VUID-VkBufferMemoryBarrier2-dstAccessMask-03925",
"VUID-VkBufferMemoryBarrier2-dstAccessMask-03926",
"VUID-VkBufferMemoryBarrier2-dstAccessMask-03927",
"VUID-VkBufferMemoryBarrier2-dstAccessMask-03928",
"VUID-VkBufferMemoryBarrier2-dstAccessMask-06256",
"VUID-VkBufferMemoryBarrier2-dstAccessMask-07272",
"VUID-VkBufferMemoryBarrier2-dstAccessMask-04858",
"VUID-VkBufferMemoryBarrier2-dstAccessMask-04859",
"VUID-VkBufferMemoryBarrier2-dstAccessMask-04860",
"VUID-VkBufferMemoryBarrier2-dstAccessMask-04861",
"VUID-VkBufferMemoryBarrier2-dstAccessMask-07455",
"VUID-VkBufferMemoryBarrier2-dstAccessMask-07456",
"VUID-VkBufferMemoryBarrier2-dstAccessMask-07457",
"VUID-VkBufferMemoryBarrier2-dstAccessMask-07458",
"VUID-VkBufferMemoryBarrier2-dstAccessMask-08118",
],
..Default::default()
}));
}
if range.is_empty() {
return Err(Box::new(ValidationError {
context: "range".into(),
problem: "is empty".into(),
vuids: &["VUID-VkBufferMemoryBarrier2-size-01188"],
..Default::default()
}));
}
if range.end > buffer.size() {
return Err(Box::new(ValidationError {
problem: "`range.end` is greater than `buffer.size()`".into(),
vuids: &[
"VUID-VkBufferMemoryBarrier2-offset-01187",
"VUID-VkBufferMemoryBarrier2-size-01189",
],
..Default::default()
}));
}
if let Some(queue_family_ownership_transfer) = queue_family_ownership_transfer {
if src_stages.intersects(PipelineStages::HOST) {
return Err(Box::new(ValidationError {
problem: "`src_stages` contains `PipelineStages::HOST`, but \
`queue_family_ownership_transfer` is `Some`"
.into(),
vuids: &["VUID-VkBufferMemoryBarrier2-srcStageMask-03851"],
..Default::default()
}));
}
if dst_stages.intersects(PipelineStages::HOST) {
return Err(Box::new(ValidationError {
problem: "`dst_stages` contains `PipelineStages::HOST`, but \
`queue_family_ownership_transfer` is `Some`"
.into(),
vuids: &["VUID-VkBufferMemoryBarrier2-srcStageMask-03851"],
..Default::default()
}));
}
let queue_family_count =
device.physical_device().queue_family_properties().len() as u32;
match queue_family_ownership_transfer {
&QueueFamilyOwnershipTransfer::ExclusiveBetweenLocal {
src_index,
dst_index,
} => {
if src_index >= queue_family_count {
return Err(Box::new(ValidationError {
context: "queue_family_ownership_transfer.src_index".into(),
problem: "is not less than the number of queue families in the \
physical device"
.into(),
vuids: &["VUID-VkBufferMemoryBarrier2-buffer-04089"],
..Default::default()
}));
}
if dst_index >= queue_family_count {
return Err(Box::new(ValidationError {
context: "queue_family_ownership_transfer.dst_index".into(),
problem: "is not less than the number of queue families in the \
physical device"
.into(),
vuids: &["VUID-VkBufferMemoryBarrier2-buffer-04089"],
..Default::default()
}));
}
if src_index == dst_index {
return Err(Box::new(ValidationError {
problem: "`queue_family_ownership_transfer.src_index` is equal to \
`queue_family_ownership_transfer.dst_index`"
.into(),
..Default::default()
}));
}
}
&QueueFamilyOwnershipTransfer::ExclusiveToExternal { src_index } => {
if src_index >= queue_family_count {
return Err(Box::new(ValidationError {
context: "queue_family_ownership_transfer.src_index".into(),
problem: "is not less than the number of queue families in the \
physical device"
.into(),
vuids: &["VUID-VkBufferMemoryBarrier2-buffer-04089"],
..Default::default()
}));
}
}
&QueueFamilyOwnershipTransfer::ExclusiveFromExternal { dst_index } => {
if dst_index >= queue_family_count {
return Err(Box::new(ValidationError {
context: "queue_family_ownership_transfer.dst_index".into(),
problem: "is not less than the number of queue families in the \
physical device"
.into(),
vuids: &["VUID-VkBufferMemoryBarrier2-buffer-04089"],
..Default::default()
}));
}
}
&QueueFamilyOwnershipTransfer::ExclusiveToForeign { src_index } => {
if src_index >= queue_family_count {
return Err(Box::new(ValidationError {
context: "queue_family_ownership_transfer.src_index".into(),
problem: "is not less than the number of queue families in the \
physical device"
.into(),
vuids: &["VUID-VkBufferMemoryBarrier2-buffer-04089"],
..Default::default()
}));
}
}
&QueueFamilyOwnershipTransfer::ExclusiveFromForeign { dst_index } => {
if dst_index >= queue_family_count {
return Err(Box::new(ValidationError {
context: "queue_family_ownership_transfer.dst_index".into(),
problem: "is not less than the number of queue families in the \
physical device"
.into(),
vuids: &["VUID-VkBufferMemoryBarrier2-buffer-04089"],
..Default::default()
}));
}
}
QueueFamilyOwnershipTransfer::ConcurrentToExternal
| QueueFamilyOwnershipTransfer::ConcurrentFromExternal
| QueueFamilyOwnershipTransfer::ConcurrentToForeign
| QueueFamilyOwnershipTransfer::ConcurrentFromForeign => (),
}
}
Ok(())
}
}
#[derive(Clone, Debug)]
pub struct ImageMemoryBarrier {
pub src_stages: PipelineStages,
pub src_access: AccessFlags,
pub dst_stages: PipelineStages,
pub dst_access: AccessFlags,
pub old_layout: ImageLayout,
pub new_layout: ImageLayout,
pub queue_family_ownership_transfer: Option<QueueFamilyOwnershipTransfer>,
pub image: Arc<Image>,
pub subresource_range: ImageSubresourceRange,
pub _ne: crate::NonExhaustive,
}
impl ImageMemoryBarrier {
#[inline]
pub fn image(image: Arc<Image>) -> Self {
Self {
src_stages: PipelineStages::empty(),
src_access: AccessFlags::empty(),
dst_stages: PipelineStages::empty(),
dst_access: AccessFlags::empty(),
old_layout: ImageLayout::Undefined,
new_layout: ImageLayout::Undefined,
queue_family_ownership_transfer: None,
image,
subresource_range: ImageSubresourceRange {
aspects: ImageAspects::empty(), mip_levels: 0..0,
array_layers: 0..0,
},
_ne: crate::NonExhaustive(()),
}
}
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
src_stages,
src_access,
dst_stages,
dst_access,
old_layout,
new_layout,
ref queue_family_ownership_transfer,
ref image,
ref subresource_range,
_ne,
} = self;
src_stages.validate_device(device).map_err(|err| {
err.add_context("src_stages")
.set_vuids(&["VUID-VkImageMemoryBarrier2-srcStageMask-parameter"])
})?;
dst_stages.validate_device(device).map_err(|err| {
err.add_context("dst_stages")
.set_vuids(&["VUID-VkImageMemoryBarrier2-dstStageMask-parameter"])
})?;
src_access.validate_device(device).map_err(|err| {
err.add_context("src_access")
.set_vuids(&["VUID-VkImageMemoryBarrier2-srcAccessMask-parameter"])
})?;
dst_access.validate_device(device).map_err(|err| {
err.add_context("dst_access")
.set_vuids(&["VUID-VkImageMemoryBarrier2-dstAccessMask-parameter"])
})?;
if !device.enabled_features().synchronization2 {
if src_stages.contains_flags2() {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains flags from `VkPipelineStageFlagBits2`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"synchronization2",
)])]),
..Default::default()
}));
}
if dst_stages.contains_flags2() {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains flags from `VkPipelineStageFlagBits2`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"synchronization2",
)])]),
..Default::default()
}));
}
if src_access.contains_flags2() {
return Err(Box::new(ValidationError {
context: "src_access".into(),
problem: "contains flags from `VkAccessFlagBits2`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"synchronization2",
)])]),
..Default::default()
}));
}
if dst_access.contains_flags2() {
return Err(Box::new(ValidationError {
context: "dst_access".into(),
problem: "contains flags from `VkAccessFlagBits2`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"synchronization2",
)])]),
..Default::default()
}));
}
}
if !device.enabled_features().geometry_shader {
if src_stages.intersects(PipelineStages::GEOMETRY_SHADER) {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::GEOMETRY_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"geometry_shader",
)])]),
vuids: &["VUID-VkImageMemoryBarrier2-srcStageMask-03929"],
}));
}
if dst_stages.intersects(PipelineStages::GEOMETRY_SHADER) {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::GEOMETRY_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"geometry_shader",
)])]),
vuids: &["VUID-VkImageMemoryBarrier2-dstStageMask-03929"],
}));
}
}
if !device.enabled_features().tessellation_shader {
if src_stages.intersects(
PipelineStages::TESSELLATION_CONTROL_SHADER
| PipelineStages::TESSELLATION_EVALUATION_SHADER,
) {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::TESSELLATION_CONTROL_SHADER` or \
`PipelineStages::TESSELLATION_EVALUATION_SHADER`"
.into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"tessellation_shader",
)])]),
vuids: &["VUID-VkImageMemoryBarrier2-srcStageMask-03930"],
}));
}
if dst_stages.intersects(
PipelineStages::TESSELLATION_CONTROL_SHADER
| PipelineStages::TESSELLATION_EVALUATION_SHADER,
) {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::TESSELLATION_CONTROL_SHADER` or \
`PipelineStages::TESSELLATION_EVALUATION_SHADER`"
.into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"tessellation_shader",
)])]),
vuids: &["VUID-VkImageMemoryBarrier2-dstStageMask-03930"],
}));
}
}
if !device.enabled_features().conditional_rendering {
if src_stages.intersects(PipelineStages::CONDITIONAL_RENDERING) {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::CONDITIONAL_RENDERING`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"conditional_rendering",
)])]),
vuids: &["VUID-VkImageMemoryBarrier2-srcStageMask-03931"],
}));
}
if dst_stages.intersects(PipelineStages::CONDITIONAL_RENDERING) {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::CONDITIONAL_RENDERING`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"conditional_rendering",
)])]),
vuids: &["VUID-VkImageMemoryBarrier2-dstStageMask-03931"],
}));
}
}
if !device.enabled_features().fragment_density_map {
if src_stages.intersects(PipelineStages::FRAGMENT_DENSITY_PROCESS) {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::FRAGMENT_DENSITY_PROCESS`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"fragment_density_map",
)])]),
vuids: &["VUID-VkImageMemoryBarrier2-srcStageMask-03932"],
}));
}
if dst_stages.intersects(PipelineStages::FRAGMENT_DENSITY_PROCESS) {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::FRAGMENT_DENSITY_PROCESS`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"fragment_density_map",
)])]),
vuids: &["VUID-VkImageMemoryBarrier2-dstStageMask-03932"],
}));
}
}
if !device.enabled_features().transform_feedback {
if src_stages.intersects(PipelineStages::TRANSFORM_FEEDBACK) {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::TRANSFORM_FEEDBACK`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"transform_feedback",
)])]),
vuids: &["VUID-VkImageMemoryBarrier2-srcStageMask-03933"],
}));
}
if dst_stages.intersects(PipelineStages::TRANSFORM_FEEDBACK) {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::TRANSFORM_FEEDBACK`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"transform_feedback",
)])]),
vuids: &["VUID-VkImageMemoryBarrier2-dstStageMask-03933"],
}));
}
}
if !device.enabled_features().mesh_shader {
if src_stages.intersects(PipelineStages::MESH_SHADER) {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::MESH_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"mesh_shader",
)])]),
vuids: &["VUID-VkImageMemoryBarrier2-srcStageMask-03934"],
}));
}
if dst_stages.intersects(PipelineStages::MESH_SHADER) {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::MESH_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"mesh_shader",
)])]),
vuids: &["VUID-VkImageMemoryBarrier2-dstStageMask-03934"],
}));
}
}
if !device.enabled_features().task_shader {
if src_stages.intersects(PipelineStages::TASK_SHADER) {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::TASK_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"task_shader",
)])]),
vuids: &["VUID-VkImageMemoryBarrier2-srcStageMask-03935"],
}));
}
if dst_stages.intersects(PipelineStages::TASK_SHADER) {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::TASK_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"task_shader",
)])]),
vuids: &["VUID-VkImageMemoryBarrier2-dstStageMask-03935"],
}));
}
}
if !(device.enabled_features().attachment_fragment_shading_rate
|| device.enabled_features().shading_rate_image)
{
if src_stages.intersects(PipelineStages::FRAGMENT_SHADING_RATE_ATTACHMENT) {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::FRAGMENT_SHADING_RATE_ATTACHMENT`".into(),
requires_one_of: RequiresOneOf(&[
RequiresAllOf(&[Requires::Feature("attachment_fragment_shading_rate")]),
RequiresAllOf(&[Requires::Feature("shading_rate_image")]),
]),
vuids: &["VUID-VkImageMemoryBarrier2-shadingRateImage-07316"],
}));
}
if dst_stages.intersects(PipelineStages::FRAGMENT_SHADING_RATE_ATTACHMENT) {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::FRAGMENT_SHADING_RATE_ATTACHMENT`".into(),
requires_one_of: RequiresOneOf(&[
RequiresAllOf(&[Requires::Feature("attachment_fragment_shading_rate")]),
RequiresAllOf(&[Requires::Feature("shading_rate_image")]),
]),
vuids: &["VUID-VkImageMemoryBarrier2-shadingRateImage-07316"],
}));
}
}
if !device.enabled_features().subpass_shading {
if src_stages.intersects(PipelineStages::SUBPASS_SHADING) {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::SUBPASS_SHADING`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"subpass_shading",
)])]),
vuids: &["VUID-VkImageMemoryBarrier2-srcStageMask-04957"],
}));
}
if dst_stages.intersects(PipelineStages::SUBPASS_SHADING) {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::SUBPASS_SHADING`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"subpass_shading",
)])]),
vuids: &["VUID-VkImageMemoryBarrier2-dstStageMask-04957"],
}));
}
}
if !device.enabled_features().invocation_mask {
if src_stages.intersects(PipelineStages::INVOCATION_MASK) {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::INVOCATION_MASK`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"invocation_mask",
)])]),
vuids: &["VUID-VkImageMemoryBarrier2-srcStageMask-04995"],
}));
}
if dst_stages.intersects(PipelineStages::INVOCATION_MASK) {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::INVOCATION_MASK`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"invocation_mask",
)])]),
vuids: &["VUID-VkImageMemoryBarrier2-dstStageMask-04995"],
}));
}
}
if !(device.enabled_extensions().nv_ray_tracing
|| device.enabled_features().ray_tracing_pipeline)
{
if src_stages.intersects(PipelineStages::RAY_TRACING_SHADER) {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::RAY_TRACING_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"ray_tracing_pipeline",
)])]),
vuids: &["VUID-VkImageMemoryBarrier2-srcStageMask-07946"],
}));
}
if dst_stages.intersects(PipelineStages::RAY_TRACING_SHADER) {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::RAY_TRACING_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"ray_tracing_pipeline",
)])]),
vuids: &["VUID-VkImageMemoryBarrier2-dstStageMask-07946"],
}));
}
}
if !AccessFlags::from(src_stages).contains(src_access) {
return Err(Box::new(ValidationError {
problem: "`src_access` contains one or more access types that are not performed \
by any stage in `src_stages`"
.into(),
vuids: &[
"VUID-VkImageMemoryBarrier2-srcAccessMask-03900",
"VUID-VkImageMemoryBarrier2-srcAccessMask-03901",
"VUID-VkImageMemoryBarrier2-srcAccessMask-03902",
"VUID-VkImageMemoryBarrier2-srcAccessMask-03903",
"VUID-VkImageMemoryBarrier2-srcAccessMask-03904",
"VUID-VkImageMemoryBarrier2-srcAccessMask-03905",
"VUID-VkImageMemoryBarrier2-srcAccessMask-03906",
"VUID-VkImageMemoryBarrier2-srcAccessMask-03907",
"VUID-VkImageMemoryBarrier2-srcAccessMask-07454",
"VUID-VkImageMemoryBarrier2-srcAccessMask-03909",
"VUID-VkImageMemoryBarrier2-srcAccessMask-03910",
"VUID-VkImageMemoryBarrier2-srcAccessMask-03911",
"VUID-VkImageMemoryBarrier2-srcAccessMask-03912",
"VUID-VkImageMemoryBarrier2-srcAccessMask-03913",
"VUID-VkImageMemoryBarrier2-srcAccessMask-03914",
"VUID-VkImageMemoryBarrier2-srcAccessMask-03915",
"VUID-VkImageMemoryBarrier2-srcAccessMask-03916",
"VUID-VkImageMemoryBarrier2-srcAccessMask-03917",
"VUID-VkImageMemoryBarrier2-srcAccessMask-03918",
"VUID-VkImageMemoryBarrier2-srcAccessMask-03919",
"VUID-VkImageMemoryBarrier2-srcAccessMask-03920",
"VUID-VkImageMemoryBarrier2-srcAccessMask-04747",
"VUID-VkImageMemoryBarrier2-srcAccessMask-03922",
"VUID-VkImageMemoryBarrier2-srcAccessMask-03923",
"VUID-VkImageMemoryBarrier2-srcAccessMask-04994",
"VUID-VkImageMemoryBarrier2-srcAccessMask-03924",
"VUID-VkImageMemoryBarrier2-srcAccessMask-03925",
"VUID-VkImageMemoryBarrier2-srcAccessMask-03926",
"VUID-VkImageMemoryBarrier2-srcAccessMask-03927",
"VUID-VkImageMemoryBarrier2-srcAccessMask-03928",
"VUID-VkImageMemoryBarrier2-srcAccessMask-06256",
"VUID-VkImageMemoryBarrier2-srcAccessMask-07272",
"VUID-VkImageMemoryBarrier2-srcAccessMask-04858",
"VUID-VkImageMemoryBarrier2-srcAccessMask-04859",
"VUID-VkImageMemoryBarrier2-srcAccessMask-04860",
"VUID-VkImageMemoryBarrier2-srcAccessMask-04861",
"VUID-VkImageMemoryBarrier2-srcAccessMask-07455",
"VUID-VkImageMemoryBarrier2-srcAccessMask-07456",
"VUID-VkImageMemoryBarrier2-srcAccessMask-07457",
"VUID-VkImageMemoryBarrier2-srcAccessMask-07458",
"VUID-VkImageMemoryBarrier2-srcAccessMask-08118",
],
..Default::default()
}));
}
if !AccessFlags::from(dst_stages).contains(dst_access) {
return Err(Box::new(ValidationError {
problem: "`dst_access` contains one or more access types that are not performed \
by any stage in `dst_stages`"
.into(),
vuids: &[
"VUID-VkImageMemoryBarrier2-dstAccessMask-03900",
"VUID-VkImageMemoryBarrier2-dstAccessMask-03901",
"VUID-VkImageMemoryBarrier2-dstAccessMask-03902",
"VUID-VkImageMemoryBarrier2-dstAccessMask-03903",
"VUID-VkImageMemoryBarrier2-dstAccessMask-03904",
"VUID-VkImageMemoryBarrier2-dstAccessMask-03905",
"VUID-VkImageMemoryBarrier2-dstAccessMask-03906",
"VUID-VkImageMemoryBarrier2-dstAccessMask-03907",
"VUID-VkImageMemoryBarrier2-dstAccessMask-07454",
"VUID-VkImageMemoryBarrier2-dstAccessMask-03909",
"VUID-VkImageMemoryBarrier2-dstAccessMask-03910",
"VUID-VkImageMemoryBarrier2-dstAccessMask-03911",
"VUID-VkImageMemoryBarrier2-dstAccessMask-03912",
"VUID-VkImageMemoryBarrier2-dstAccessMask-03913",
"VUID-VkImageMemoryBarrier2-dstAccessMask-03914",
"VUID-VkImageMemoryBarrier2-dstAccessMask-03915",
"VUID-VkImageMemoryBarrier2-dstAccessMask-03916",
"VUID-VkImageMemoryBarrier2-dstAccessMask-03917",
"VUID-VkImageMemoryBarrier2-dstAccessMask-03918",
"VUID-VkImageMemoryBarrier2-dstAccessMask-03919",
"VUID-VkImageMemoryBarrier2-dstAccessMask-03920",
"VUID-VkImageMemoryBarrier2-dstAccessMask-04747",
"VUID-VkImageMemoryBarrier2-dstAccessMask-03922",
"VUID-VkImageMemoryBarrier2-dstAccessMask-03923",
"VUID-VkImageMemoryBarrier2-dstAccessMask-04994",
"VUID-VkImageMemoryBarrier2-dstAccessMask-03924",
"VUID-VkImageMemoryBarrier2-dstAccessMask-03925",
"VUID-VkImageMemoryBarrier2-dstAccessMask-03926",
"VUID-VkImageMemoryBarrier2-dstAccessMask-03927",
"VUID-VkImageMemoryBarrier2-dstAccessMask-03928",
"VUID-VkImageMemoryBarrier2-dstAccessMask-06256",
"VUID-VkImageMemoryBarrier2-dstAccessMask-07272",
"VUID-VkImageMemoryBarrier2-dstAccessMask-04858",
"VUID-VkImageMemoryBarrier2-dstAccessMask-04859",
"VUID-VkImageMemoryBarrier2-dstAccessMask-04860",
"VUID-VkImageMemoryBarrier2-dstAccessMask-04861",
"VUID-VkImageMemoryBarrier2-dstAccessMask-07455",
"VUID-VkImageMemoryBarrier2-dstAccessMask-07456",
"VUID-VkImageMemoryBarrier2-dstAccessMask-07457",
"VUID-VkImageMemoryBarrier2-dstAccessMask-07458",
"VUID-VkImageMemoryBarrier2-dstAccessMask-08118",
],
..Default::default()
}));
}
subresource_range
.validate(device)
.map_err(|err| err.add_context("subresource_range"))?;
if subresource_range.mip_levels.end > image.mip_levels() {
return Err(Box::new(ValidationError {
problem: "`subresource_range.mip_levels.end` is greater than \
`image.mip_levels()`"
.into(),
vuids: &[
"VUID-VkImageMemoryBarrier2-subresourceRange-01486",
"VUID-VkImageMemoryBarrier2-subresourceRange-01724",
],
..Default::default()
}));
}
if subresource_range.array_layers.end > image.array_layers() {
return Err(Box::new(ValidationError {
problem: "`subresource_range.array_layers.end` is greater than \
`image.array_layers()`"
.into(),
vuids: &[
"VUID-VkImageMemoryBarrier2-subresourceRange-01488",
"VUID-VkImageMemoryBarrier2-subresourceRange-01725",
],
..Default::default()
}));
}
let image_format_aspects = image.format().aspects();
if !image_format_aspects.contains(subresource_range.aspects) {
return Err(Box::new(ValidationError {
problem: "`subresource_range.aspects` is not a subset of \
`image.format().aspects()`"
.into(),
vuids: &[
"VUID-VkImageMemoryBarrier2-image-01672",
"VUID-VkImageMemoryBarrier2-image-03319",
],
..Default::default()
}));
}
if image_format_aspects.intersects(ImageAspects::COLOR)
&& !image.flags().intersects(ImageCreateFlags::DISJOINT)
&& subresource_range.aspects != ImageAspects::COLOR
{
return Err(Box::new(ValidationError {
problem: "`image.format()` is a color format, and \
`image.flags()` does not contain `ImageCreateFlags::DISJOINT`, but \
`subresource_range.aspects` is not `ImageAspects::COLOR`"
.into(),
vuids: &["VUID-VkImageMemoryBarrier2-image-01671"],
..Default::default()
}));
}
if image_format_aspects.contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
&& !subresource_range
.aspects
.contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
&& !device.enabled_features().separate_depth_stencil_layouts
{
return Err(Box::new(ValidationError {
problem: "`image.format()` has both a depth and a stencil component, and \
`subresource_range.aspects` does not contain both \
`ImageAspects::DEPTH` and `ImageAspects::STENCIL`"
.into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"separate_depth_stencil_layouts",
)])]),
vuids: &["VUID-VkImageMemoryBarrier2-image-03320"],
..Default::default()
}));
}
if subresource_range.aspects.intersects(ImageAspects::DEPTH) {
if matches!(
old_layout,
ImageLayout::StencilAttachmentOptimal | ImageLayout::StencilReadOnlyOptimal
) {
return Err(Box::new(ValidationError {
problem: "`subresource_range.aspects` contains `ImageAspects::DEPTH`, but \
`old_layout` is `ImageLayout::StencilAttachmentOptimal` or \
`ImageLayout::StencilReadOnlyOptimal`"
.into(),
vuids: &["VUID-VkImageMemoryBarrier2-aspectMask-08702"],
..Default::default()
}));
}
if matches!(
new_layout,
ImageLayout::StencilAttachmentOptimal | ImageLayout::StencilReadOnlyOptimal
) {
return Err(Box::new(ValidationError {
problem: "`subresource_range.aspects` contains `ImageAspects::DEPTH`, but \
`new_layout` is `ImageLayout::StencilAttachmentOptimal` or \
`ImageLayout::StencilReadOnlyOptimal`"
.into(),
vuids: &["VUID-VkImageMemoryBarrier2-aspectMask-08702"],
..Default::default()
}));
}
}
if subresource_range.aspects.intersects(ImageAspects::STENCIL) {
if matches!(
old_layout,
ImageLayout::StencilAttachmentOptimal | ImageLayout::StencilReadOnlyOptimal
) {
return Err(Box::new(ValidationError {
problem: "`subresource_range.aspects` contains `ImageAspects::STENCIL`, but \
`old_layout` is `ImageLayout::DepthAttachmentOptimal` or \
`ImageLayout::DepthReadOnlyOptimal`"
.into(),
vuids: &["VUID-VkImageMemoryBarrier2-aspectMask-08703"],
..Default::default()
}));
}
if matches!(
new_layout,
ImageLayout::DepthAttachmentOptimal | ImageLayout::DepthReadOnlyOptimal
) {
return Err(Box::new(ValidationError {
problem: "`subresource_range.aspects` contains `ImageAspects::STENCIL`, but \
`new_layout` is `ImageLayout::DepthAttachmentOptimal` or \
`ImageLayout::DepthReadOnlyOptimal`"
.into(),
vuids: &["VUID-VkImageMemoryBarrier2-aspectMask-08703"],
..Default::default()
}));
}
}
if let Some(queue_family_ownership_transfer) = queue_family_ownership_transfer {
if src_stages.intersects(PipelineStages::HOST) {
return Err(Box::new(ValidationError {
problem: "`src_stages` contains `PipelineStages::HOST`, but \
`queue_family_ownership_transfer` is `Some`"
.into(),
vuids: &["VUID-VkImageMemoryBarrier2-srcStageMask-03854"],
..Default::default()
}));
}
if dst_stages.intersects(PipelineStages::HOST) {
return Err(Box::new(ValidationError {
problem: "`dst_stages` contains `PipelineStages::HOST`, but \
`queue_family_ownership_transfer` is `Some`"
.into(),
vuids: &["VUID-VkImageMemoryBarrier2-srcStageMask-03854"],
..Default::default()
}));
}
let queue_family_count =
device.physical_device().queue_family_properties().len() as u32;
match queue_family_ownership_transfer {
&QueueFamilyOwnershipTransfer::ExclusiveBetweenLocal {
src_index,
dst_index,
} => {
if src_index >= queue_family_count {
return Err(Box::new(ValidationError {
context: "queue_family_ownership_transfer.src_index".into(),
problem: "is not less than the number of queue families in the \
physical device"
.into(),
vuids: &["VUID-VkImageMemoryBarrier2-image-04072"],
..Default::default()
}));
}
if dst_index >= queue_family_count {
return Err(Box::new(ValidationError {
context: "queue_family_ownership_transfer.dst_index".into(),
problem: "is not less than the number of queue families in the \
physical device"
.into(),
vuids: &["VUID-VkImageMemoryBarrier2-image-04072"],
..Default::default()
}));
}
if src_index == dst_index {
return Err(Box::new(ValidationError {
problem: "`queue_family_ownership_transfer.src_index` is equal to \
`queue_family_ownership_transfer.dst_index`"
.into(),
..Default::default()
}));
}
}
&QueueFamilyOwnershipTransfer::ExclusiveToExternal { src_index } => {
if src_index >= queue_family_count {
return Err(Box::new(ValidationError {
context: "queue_family_ownership_transfer.src_index".into(),
problem: "is not less than the number of queue families in the \
physical device"
.into(),
vuids: &["VUID-VkImageMemoryBarrier2-image-04072"],
..Default::default()
}));
}
}
&QueueFamilyOwnershipTransfer::ExclusiveFromExternal { dst_index } => {
if dst_index >= queue_family_count {
return Err(Box::new(ValidationError {
context: "queue_family_ownership_transfer.dst_index".into(),
problem: "is not less than the number of queue families in the \
physical device"
.into(),
vuids: &["VUID-VkImageMemoryBarrier2-image-04072"],
..Default::default()
}));
}
}
&QueueFamilyOwnershipTransfer::ExclusiveToForeign { src_index } => {
if src_index >= queue_family_count {
return Err(Box::new(ValidationError {
context: "queue_family_ownership_transfer.src_index".into(),
problem: "is not less than the number of queue families in the \
physical device"
.into(),
vuids: &["VUID-VkImageMemoryBarrier2-image-04072"],
..Default::default()
}));
}
}
&QueueFamilyOwnershipTransfer::ExclusiveFromForeign { dst_index } => {
if dst_index >= queue_family_count {
return Err(Box::new(ValidationError {
context: "queue_family_ownership_transfer.dst_index".into(),
problem: "is not less than the number of queue families in the \
physical device"
.into(),
vuids: &["VUID-VkImageMemoryBarrier2-image-04072"],
..Default::default()
}));
}
}
QueueFamilyOwnershipTransfer::ConcurrentToExternal
| QueueFamilyOwnershipTransfer::ConcurrentFromExternal
| QueueFamilyOwnershipTransfer::ConcurrentToForeign
| QueueFamilyOwnershipTransfer::ConcurrentFromForeign => (),
}
}
let is_image_layout_transition =
!device.enabled_features().synchronization2 || old_layout != new_layout;
let is_queue_family_ownership_transfer = queue_family_ownership_transfer.is_some();
if is_image_layout_transition || is_queue_family_ownership_transfer {
match old_layout {
ImageLayout::ColorAttachmentOptimal => {
if !image.usage().intersects(ImageUsage::COLOR_ATTACHMENT) {
return Err(Box::new(ValidationError {
problem: "`old_layout` is `ImageLayout::ColorAttachmentOptimal`, but \
`image.usage()` does not contain `ImageUsage::COLOR_ATTACHMENT`"
.into(),
vuids: &["VUID-VkImageMemoryBarrier2-oldLayout-01208"],
..Default::default()
}));
}
}
ImageLayout::DepthStencilAttachmentOptimal
| ImageLayout::DepthStencilReadOnlyOptimal
| ImageLayout::DepthReadOnlyStencilAttachmentOptimal
| ImageLayout::DepthAttachmentStencilReadOnlyOptimal
| ImageLayout::DepthAttachmentOptimal
| ImageLayout::StencilAttachmentOptimal => {
if !image
.usage()
.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
{
return Err(Box::new(ValidationError {
problem: "`old_layout` is \
`ImageLayout::DepthStencilAttachmentOptimal`, \
`ImageLayout::DepthStencilReadOnlyOptimal`, \
`ImageLayout::DepthReadOnlyStencilAttachmentOptimal`, \
`ImageLayout::DepthAttachmentStencilReadOnlyOptimal`, \
`ImageLayout::DepthAttachmentOptimal` or \
`ImageLayout::StencilAttachmentOptimal`, but \
`image.usage()` does not contain \
`ImageUsage::DEPTH_STENCIL_ATTACHMENT`"
.into(),
vuids: &[
"VUID-VkImageMemoryBarrier2-oldLayout-01209",
"VUID-VkImageMemoryBarrier2-oldLayout-01210",
"VUID-VkImageMemoryBarrier2-oldLayout-01658",
"VUID-VkImageMemoryBarrier2-oldLayout-01659",
"VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-04066",
"VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-04068",
],
..Default::default()
}));
}
}
ImageLayout::ShaderReadOnlyOptimal => {
if !image
.usage()
.intersects(ImageUsage::SAMPLED | ImageUsage::INPUT_ATTACHMENT)
{
return Err(Box::new(ValidationError {
problem: "`old_layout` is `ImageLayout::ShaderReadOnlyOptimal`, but \
`image.usage()` does not contain `ImageUsage::SAMPLED` or \
`ImageUsage::INPUT_ATTACHMENT`"
.into(),
vuids: &["VUID-VkImageMemoryBarrier2-oldLayout-01211"],
..Default::default()
}));
}
}
ImageLayout::TransferSrcOptimal => {
if !image.usage().intersects(ImageUsage::TRANSFER_SRC) {
return Err(Box::new(ValidationError {
problem: "`old_layout` is `ImageLayout::TransferSrcOptimal`, but \
`image.usage()` does not contain `ImageUsage::TRANSFER_SRC`"
.into(),
vuids: &["VUID-VkImageMemoryBarrier2-oldLayout-01212"],
..Default::default()
}));
}
}
ImageLayout::TransferDstOptimal => {
if !image.usage().intersects(ImageUsage::TRANSFER_DST) {
return Err(Box::new(ValidationError {
problem: "`old_layout` is `ImageLayout::TransferDstOptimal`, but \
`image.usage()` does not contain `ImageUsage::TRANSFER_DST`"
.into(),
vuids: &["VUID-VkImageMemoryBarrier2-oldLayout-01213"],
..Default::default()
}));
}
}
ImageLayout::Preinitialized => todo!(),
ImageLayout::DepthReadOnlyOptimal | ImageLayout::StencilReadOnlyOptimal => {
if !image.usage().intersects(
ImageUsage::DEPTH_STENCIL_ATTACHMENT
| ImageUsage::SAMPLED
| ImageUsage::INPUT_ATTACHMENT,
) {
return Err(Box::new(ValidationError {
problem: "`old_layout` is `ImageLayout::DepthReadOnlyOptimal` or \
`ImageLayout::StencilReadOnlyOptimal`, but \
`image.usage()` does not contain \
`ImageUsage::DEPTH_STENCIL_ATTACHMENT`, `ImageUsage::SAMPLED` or \
`ImageUsage::INPUT_ATTACHMENT`"
.into(),
vuids: &[
"VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-04065",
"VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-04067",
],
..Default::default()
}));
}
}
ImageLayout::Undefined | ImageLayout::General | ImageLayout::PresentSrc => (),
}
match new_layout {
ImageLayout::Undefined | ImageLayout::Preinitialized => {
return Err(Box::new(ValidationError {
context: "new_layout".into(),
problem: "is `ImageLayout::Undefined` or `ImageLayout::Preinitialized`"
.into(),
vuids: &["VUID-VkImageMemoryBarrier2-newLayout-01198"],
..Default::default()
}));
}
ImageLayout::ColorAttachmentOptimal => {
if !image.usage().intersects(ImageUsage::COLOR_ATTACHMENT) {
return Err(Box::new(ValidationError {
problem: "`new_layout` is `ImageLayout::ColorAttachmentOptimal`, but \
`image.usage()` does not contain `ImageUsage::COLOR_ATTACHMENT`"
.into(),
vuids: &["VUID-VkImageMemoryBarrier2-oldLayout-01208"],
..Default::default()
}));
}
}
ImageLayout::DepthStencilAttachmentOptimal
| ImageLayout::DepthStencilReadOnlyOptimal
| ImageLayout::DepthReadOnlyStencilAttachmentOptimal
| ImageLayout::DepthAttachmentStencilReadOnlyOptimal
| ImageLayout::DepthAttachmentOptimal
| ImageLayout::StencilAttachmentOptimal => {
if !image
.usage()
.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
{
return Err(Box::new(ValidationError {
problem: "`new_layout` is \
`ImageLayout::DepthStencilAttachmentOptimal`, \
`ImageLayout::DepthStencilReadOnlyOptimal`, \
`ImageLayout::DepthReadOnlyStencilAttachmentOptimal`, \
`ImageLayout::DepthAttachmentStencilReadOnlyOptimal`, \
`ImageLayout::DepthAttachmentOptimal` or \
`ImageLayout::StencilAttachmentOptimal`, but \
`image.usage()` does not contain \
`ImageUsage::DEPTH_STENCIL_ATTACHMENT`"
.into(),
vuids: &[
"VUID-VkImageMemoryBarrier2-oldLayout-01209",
"VUID-VkImageMemoryBarrier2-oldLayout-01210",
"VUID-VkImageMemoryBarrier2-oldLayout-01658",
"VUID-VkImageMemoryBarrier2-oldLayout-01659",
"VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-04066",
"VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-04068",
],
..Default::default()
}));
}
}
ImageLayout::ShaderReadOnlyOptimal => {
if !image
.usage()
.intersects(ImageUsage::SAMPLED | ImageUsage::INPUT_ATTACHMENT)
{
return Err(Box::new(ValidationError {
problem: "`new_layout` is `ImageLayout::ShaderReadOnlyOptimal`, but \
`image.usage()` does not contain `ImageUsage::SAMPLED` or \
`ImageUsage::INPUT_ATTACHMENT`"
.into(),
vuids: &["VUID-VkImageMemoryBarrier2-oldLayout-01211"],
..Default::default()
}));
}
}
ImageLayout::TransferSrcOptimal => {
if !image.usage().intersects(ImageUsage::TRANSFER_SRC) {
return Err(Box::new(ValidationError {
problem: "`new_layout` is `ImageLayout::TransferSrcOptimal`, but \
`image.usage()` does not contain `ImageUsage::TRANSFER_SRC`"
.into(),
vuids: &["VUID-VkImageMemoryBarrier2-oldLayout-01212"],
..Default::default()
}));
}
}
ImageLayout::TransferDstOptimal => {
if !image.usage().intersects(ImageUsage::TRANSFER_DST) {
return Err(Box::new(ValidationError {
problem: "`new_layout` is `ImageLayout::TransferDstOptimal`, but \
`image.usage()` does not contain `ImageUsage::TRANSFER_DST`"
.into(),
vuids: &["VUID-VkImageMemoryBarrier2-oldLayout-01213"],
..Default::default()
}));
}
}
ImageLayout::DepthReadOnlyOptimal | ImageLayout::StencilReadOnlyOptimal => {
if !image.usage().intersects(
ImageUsage::DEPTH_STENCIL_ATTACHMENT
| ImageUsage::SAMPLED
| ImageUsage::INPUT_ATTACHMENT,
) {
return Err(Box::new(ValidationError {
problem: "`new_layout` is `ImageLayout::DepthReadOnlyOptimal` or \
`ImageLayout::StencilReadOnlyOptimal`, but \
`image.usage()` does not contain \
`ImageUsage::DEPTH_STENCIL_ATTACHMENT`, `ImageUsage::SAMPLED` or \
`ImageUsage::INPUT_ATTACHMENT`"
.into(),
vuids: &[
"VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-04065",
"VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-04067",
],
..Default::default()
}));
}
}
ImageLayout::General | ImageLayout::PresentSrc => (),
}
if src_stages.intersects(PipelineStages::HOST)
&& !matches!(
old_layout,
ImageLayout::Preinitialized | ImageLayout::Undefined | ImageLayout::General
)
{
return Err(Box::new(ValidationError {
problem: "`src_stages` contains `PipelineStages::HOST`, but \
`old_layout` is not `ImageLayout::Preinitialized`, \
`ImageLayout::Undefined` or `ImageLayout::General`"
.into(),
vuids: &["VUID-VkImageMemoryBarrier2-srcStageMask-03855"],
..Default::default()
}));
}
}
Ok(())
}
}
#[derive(Clone, Copy, Debug)]
pub enum QueueFamilyOwnershipTransfer {
ExclusiveBetweenLocal {
src_index: u32,
dst_index: u32,
},
ExclusiveToExternal {
src_index: u32,
},
ExclusiveFromExternal {
dst_index: u32,
},
ExclusiveToForeign {
src_index: u32,
},
ExclusiveFromForeign {
dst_index: u32,
},
ConcurrentToExternal,
ConcurrentFromExternal,
ConcurrentToForeign,
ConcurrentFromForeign,
}
impl From<QueueFamilyOwnershipTransfer> for (u32, u32) {
fn from(val: QueueFamilyOwnershipTransfer) -> Self {
match val {
QueueFamilyOwnershipTransfer::ExclusiveBetweenLocal {
src_index,
dst_index,
} => (src_index, dst_index),
QueueFamilyOwnershipTransfer::ExclusiveToExternal { src_index } => {
(src_index, ash::vk::QUEUE_FAMILY_EXTERNAL)
}
QueueFamilyOwnershipTransfer::ExclusiveFromExternal { dst_index } => {
(ash::vk::QUEUE_FAMILY_EXTERNAL, dst_index)
}
QueueFamilyOwnershipTransfer::ExclusiveToForeign { src_index } => {
(src_index, ash::vk::QUEUE_FAMILY_FOREIGN_EXT)
}
QueueFamilyOwnershipTransfer::ExclusiveFromForeign { dst_index } => {
(ash::vk::QUEUE_FAMILY_FOREIGN_EXT, dst_index)
}
QueueFamilyOwnershipTransfer::ConcurrentToExternal => (
ash::vk::QUEUE_FAMILY_IGNORED,
ash::vk::QUEUE_FAMILY_EXTERNAL,
),
QueueFamilyOwnershipTransfer::ConcurrentFromExternal => (
ash::vk::QUEUE_FAMILY_EXTERNAL,
ash::vk::QUEUE_FAMILY_IGNORED,
),
QueueFamilyOwnershipTransfer::ConcurrentToForeign => (
ash::vk::QUEUE_FAMILY_IGNORED,
ash::vk::QUEUE_FAMILY_FOREIGN_EXT,
),
QueueFamilyOwnershipTransfer::ConcurrentFromForeign => (
ash::vk::QUEUE_FAMILY_FOREIGN_EXT,
ash::vk::QUEUE_FAMILY_IGNORED,
),
}
}
}