Skip to main content

rotex_vulkan/backend/vulkan/
pass.rs

1use ash::vk;
2
3use super::device::Device;
4
5#[derive(Debug, Clone)]
6pub struct SubpassBlueprint {
7    pub color_attachments: Vec<u32>,
8    pub depth_attachment: Option<u32>,
9}
10
11pub struct RenderPass {
12    pub(crate) render_pass: vk::RenderPass,
13    attachments: Vec<vk::AttachmentDescription>,
14}
15
16impl RenderPass {
17    pub fn handle(&self) -> vk::RenderPass {
18        self.render_pass
19    }
20
21    pub fn attachments(&self) -> &[vk::AttachmentDescription] {
22        &self.attachments
23    }
24
25    pub fn destroy(&self, device: &Device) {
26        unsafe {
27            device
28                .logical_device()
29                .destroy_render_pass(self.render_pass, None);
30        }
31    }
32}
33
34pub struct RenderPassBuilder {
35    attachments: Vec<vk::AttachmentDescription>,
36    subpasses: Vec<SubpassBlueprint>,
37    dependencies: Vec<vk::SubpassDependency>,
38}
39
40impl RenderPassBuilder {
41    pub fn new() -> Self {
42        Self {
43            attachments: Vec::new(),
44            subpasses: Vec::new(),
45            dependencies: Vec::new(),
46        }
47    }
48
49    pub fn with_attachment(mut self, attachment: vk::AttachmentDescription) -> Self {
50        self.attachments.push(attachment);
51        self
52    }
53
54    pub fn with_subpass(mut self, subpass: SubpassBlueprint) -> Self {
55        self.subpasses.push(subpass);
56        self
57    }
58
59    pub fn with_dependency(mut self, dependency: vk::SubpassDependency) -> Self {
60        self.dependencies.push(dependency);
61        self
62    }
63
64    pub fn build(self, device: &Device) -> Result<RenderPass, vk::Result> {
65        let mut all_color_refs: Vec<Vec<vk::AttachmentReference>> =
66            Vec::with_capacity(self.subpasses.len());
67        let mut all_depth_refs: Vec<Option<vk::AttachmentReference>> =
68            Vec::with_capacity(self.subpasses.len());
69
70        for blueprint in &self.subpasses {
71            let color_refs: Vec<vk::AttachmentReference> = blueprint
72                .color_attachments
73                .iter()
74                .map(|&idx| {
75                    vk::AttachmentReference::default()
76                        .attachment(idx)
77                        .layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL)
78                })
79                .collect();
80            all_color_refs.push(color_refs);
81
82            let depth_ref = blueprint.depth_attachment.map(|idx| {
83                vk::AttachmentReference::default()
84                    .attachment(idx)
85                    .layout(vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL)
86            });
87            all_depth_refs.push(depth_ref);
88        }
89
90        let mut vk_subpasses: Vec<vk::SubpassDescription> = Vec::with_capacity(self.subpasses.len());
91
92        for i in 0..self.subpasses.len() {
93            let mut subpass_desc = vk::SubpassDescription::default()
94                .pipeline_bind_point(vk::PipelineBindPoint::GRAPHICS)
95                .color_attachments(&all_color_refs[i]);
96
97            if let Some(depth_ref) = &all_depth_refs[i] {
98                subpass_desc = subpass_desc.depth_stencil_attachment(depth_ref);
99            }
100
101            vk_subpasses.push(subpass_desc);
102        }
103
104        let render_pass_info = vk::RenderPassCreateInfo::default()
105            .attachments(&self.attachments)
106            .subpasses(&vk_subpasses)
107            .dependencies(&self.dependencies);
108
109        let render_pass = unsafe {
110            device
111                .logical_device()
112                .create_render_pass(&render_pass_info, None)?
113        };
114        Ok(RenderPass {
115            render_pass,
116            attachments: self.attachments,
117        })
118    }
119}