| 1 | use crate::image::{ImageInner, color_range}; |
| 2 | use ash::vk; |
| 3 | |
| 4 | /// A full barrier between all earlier and later work on the image, optionally |
| 5 | /// transferring ownership between queue families. Coarse, but correct for |
| 6 | /// every transition the renderer makes. |
| 7 | pub(crate) unsafe fn barrier( |
| 8 | d: &ash::Device, |
| 9 | cmd: vk::CommandBuffer, |
| 10 | image: vk::Image, |
| 11 | old: vk::ImageLayout, |
| 12 | new: vk::ImageLayout, |
| 13 | src_family: u32, |
| 14 | dst_family: u32, |
| 15 | ) { |
| 16 | let b = [vk::ImageMemoryBarrier2::default() |
| 17 | .src_stage_mask(vk::PipelineStageFlags2::ALL_COMMANDS) |
| 18 | .src_access_mask(vk::AccessFlags2::MEMORY_WRITE) |
| 19 | .dst_stage_mask(vk::PipelineStageFlags2::ALL_COMMANDS) |
| 20 | .dst_access_mask(vk::AccessFlags2::MEMORY_READ | vk::AccessFlags2::MEMORY_WRITE) |
| 21 | .old_layout(old) |
| 22 | .new_layout(new) |
| 23 | .src_queue_family_index(src_family) |
| 24 | .dst_queue_family_index(dst_family) |
| 25 | .image(image) |
| 26 | .subresource_range(color_range())]; |
| 27 | unsafe { |
| 28 | d.cmd_pipeline_barrier2( |
| 29 | cmd, |
| 30 | &vk::DependencyInfo::default().image_memory_barriers(&b), |
| 31 | ) |
| 32 | }; |
| 33 | } |
| 34 | |
| 35 | /// Moves an image into `layout` for use on this queue. Dmabuf images come |
| 36 | /// from the foreign queue family in the general layout, others continue from |
| 37 | /// their tracked layout. |
| 38 | pub(crate) unsafe fn acquire( |
| 39 | d: &ash::Device, |
| 40 | cmd: vk::CommandBuffer, |
| 41 | family: u32, |
| 42 | image: &ImageInner, |
| 43 | layout: vk::ImageLayout, |
| 44 | ) { |
| 45 | if image.external { |
| 46 | unsafe { |
| 47 | barrier( |
| 48 | d, |
| 49 | cmd, |
| 50 | image.image, |
| 51 | vk::ImageLayout::GENERAL, |
| 52 | layout, |
| 53 | vk::QUEUE_FAMILY_FOREIGN_EXT, |
| 54 | family, |
| 55 | ) |
| 56 | }; |
| 57 | } else { |
| 58 | let old = image.layout(); |
| 59 | if old != layout { |
| 60 | unsafe { |
| 61 | barrier( |
| 62 | d, |
| 63 | cmd, |
| 64 | image.image, |
| 65 | old, |
| 66 | layout, |
| 67 | vk::QUEUE_FAMILY_IGNORED, |
| 68 | vk::QUEUE_FAMILY_IGNORED, |
| 69 | ) |
| 70 | }; |
| 71 | image.set_layout(layout); |
| 72 | } |
| 73 | } |
| 74 | } |
| 75 | |
| 76 | /// Hands a dmabuf image back to the foreign queue family after use. |
| 77 | pub(crate) unsafe fn release( |
| 78 | d: &ash::Device, |
| 79 | cmd: vk::CommandBuffer, |
| 80 | family: u32, |
| 81 | image: &ImageInner, |
| 82 | layout: vk::ImageLayout, |
| 83 | ) { |
| 84 | if image.external { |
| 85 | unsafe { |
| 86 | barrier( |
| 87 | d, |
| 88 | cmd, |
| 89 | image.image, |
| 90 | layout, |
| 91 | vk::ImageLayout::GENERAL, |
| 92 | family, |
| 93 | vk::QUEUE_FAMILY_FOREIGN_EXT, |
| 94 | ) |
| 95 | }; |
| 96 | } |
| 97 | } |