atagen

monolith

public
Star0
Watch0
ad1f04ba8cb292f72b399096c225ffd592040418
1
ssh://brewery@pls.lobotomise.me:33/atagen/monolith.git
crates/render-vk/src/barrier.rsRust121 lines3.4 KB
1
use crate::image::{ImageInner, color_range};
2
use ash::vk;
3
use std::sync::Arc;
4
5
/// Layout changes recorded into a command buffer that has not been submitted.
6
/// Images keep their old layout until `commit`, so a failed submit leaves the
7
/// tracking true to what the GPU has done.
8
#[derive(Default)]
9
pub(crate) struct LayoutLog(Vec<(Arc<ImageInner>, vk::ImageLayout)>);
10
11
impl LayoutLog {
12
    fn current(&self, image: &Arc<ImageInner>) -> vk::ImageLayout {
13
        self.0
14
            .iter()
15
            .rev()
16
            .find(|(i, _)| Arc::ptr_eq(i, image))
17
            .map_or_else(|| image.layout(), |(_, layout)| *layout)
18
    }
19
20
    pub fn commit(self) {
21
        for (image, layout) in self.0 {
22
            image.set_layout(layout);
23
        }
24
    }
25
}
26
27
/// A full barrier between all earlier and later work on the image, optionally
28
/// transferring ownership between queue families. Coarse, but correct for
29
/// every transition the renderer makes.
30
pub(crate) unsafe fn barrier(
31
    d: &ash::Device,
32
    cmd: vk::CommandBuffer,
33
    image: vk::Image,
34
    old: vk::ImageLayout,
35
    new: vk::ImageLayout,
36
    src_family: u32,
37
    dst_family: u32,
38
) {
39
    let b = [vk::ImageMemoryBarrier2::default()
40
        .src_stage_mask(vk::PipelineStageFlags2::ALL_COMMANDS)
41
        .src_access_mask(vk::AccessFlags2::MEMORY_WRITE)
42
        .dst_stage_mask(vk::PipelineStageFlags2::ALL_COMMANDS)
43
        .dst_access_mask(vk::AccessFlags2::MEMORY_READ | vk::AccessFlags2::MEMORY_WRITE)
44
        .old_layout(old)
45
        .new_layout(new)
46
        .src_queue_family_index(src_family)
47
        .dst_queue_family_index(dst_family)
48
        .image(image)
49
        .subresource_range(color_range())];
50
    unsafe {
51
        d.cmd_pipeline_barrier2(
52
            cmd,
53
            &vk::DependencyInfo::default().image_memory_barriers(&b),
54
        )
55
    };
56
}
57
58
/// Moves an image into `layout` for use on this queue. Dmabuf images come
59
/// from the foreign queue family in the general layout, others continue from
60
/// their tracked layout.
61
pub(crate) unsafe fn acquire(
62
    d: &ash::Device,
63
    cmd: vk::CommandBuffer,
64
    family: u32,
65
    image: &Arc<ImageInner>,
66
    layout: vk::ImageLayout,
67
    log: &mut LayoutLog,
68
) {
69
    if image.external {
70
        unsafe {
71
            barrier(
72
                d,
73
                cmd,
74
                image.image,
75
                vk::ImageLayout::GENERAL,
76
                layout,
77
                vk::QUEUE_FAMILY_FOREIGN_EXT,
78
                family,
79
            )
80
        };
81
    } else {
82
        let old = log.current(image);
83
        if old != layout {
84
            unsafe {
85
                barrier(
86
                    d,
87
                    cmd,
88
                    image.image,
89
                    old,
90
                    layout,
91
                    vk::QUEUE_FAMILY_IGNORED,
92
                    vk::QUEUE_FAMILY_IGNORED,
93
                )
94
            };
95
            log.0.push((image.clone(), layout));
96
        }
97
    }
98
}
99
100
/// Hands a dmabuf image back to the foreign queue family after use.
101
pub(crate) unsafe fn release(
102
    d: &ash::Device,
103
    cmd: vk::CommandBuffer,
104
    family: u32,
105
    image: &ImageInner,
106
    layout: vk::ImageLayout,
107
) {
108
    if image.external {
109
        unsafe {
110
            barrier(
111
                d,
112
                cmd,
113
                image.image,
114
                layout,
115
                vk::ImageLayout::GENERAL,
116
                family,
117
                vk::QUEUE_FAMILY_FOREIGN_EXT,
118
            )
119
        };
120
    }
121
}