bort_vk/
render_pass.rs

1use crate::{Device, DeviceOwned, ALLOCATION_CALLBACK_NONE};
2use ash::{
3    prelude::VkResult,
4    vk::{self, Handle},
5};
6use std::sync::Arc;
7
8#[derive(Clone)]
9pub struct RenderPass {
10    handle: vk::RenderPass,
11    properties: RenderPassProperties,
12
13    // dependencies
14    device: Arc<Device>,
15}
16
17impl RenderPass {
18    pub fn new(
19        device: Arc<Device>,
20        attachment_descriptions: Vec<vk::AttachmentDescription>,
21        subpasses: Vec<Subpass>,
22        subpass_dependencies: Vec<vk::SubpassDependency>,
23    ) -> VkResult<Self> {
24        let subpass_descriptions: Vec<vk::SubpassDescription> = subpasses
25            .iter()
26            .map(|subpass| subpass.subpass_description_builder().build())
27            .collect();
28
29        let render_pass_info = vk::RenderPassCreateInfo::builder()
30            .attachments(&attachment_descriptions)
31            .subpasses(&subpass_descriptions)
32            .dependencies(&subpass_dependencies);
33
34        let handle = unsafe {
35            device
36                .inner()
37                .create_render_pass(&render_pass_info, ALLOCATION_CALLBACK_NONE)
38        }?;
39
40        Ok(Self {
41            handle,
42            properties: RenderPassProperties {
43                attachment_descriptions,
44                subpasses,
45                subpass_dependencies,
46            },
47            device,
48        })
49    }
50
51    /// Safety:
52    ///
53    /// For each subpass:
54    /// - if `subpass_description.p_color_attachments` is not null it must point to an array with
55    ///   `subpass_description.color_attachment_count` many elements.
56    /// - if `subpass_description.p_input_attachments` is not null it must point to an array with
57    ///   `subpass_description.input_attachment_count` many elements.
58    pub unsafe fn new_from_create_info(
59        device: Arc<Device>,
60        create_info_builder: vk::RenderPassCreateInfoBuilder,
61    ) -> VkResult<Self> {
62        let properties =
63            unsafe { RenderPassProperties::from_create_info_builder(&create_info_builder) };
64
65        let handle = unsafe {
66            device
67                .inner()
68                .create_render_pass(&create_info_builder, ALLOCATION_CALLBACK_NONE)
69        }?;
70
71        Ok(Self {
72            handle,
73            properties,
74            device,
75        })
76    }
77
78    // Getters
79
80    #[inline]
81    pub fn handle(&self) -> vk::RenderPass {
82        self.handle
83    }
84
85    #[inline]
86    pub fn properties(&self) -> &RenderPassProperties {
87        &self.properties
88    }
89}
90
91impl DeviceOwned for RenderPass {
92    #[inline]
93    fn device(&self) -> &Arc<Device> {
94        &self.device
95    }
96
97    #[inline]
98    fn handle_raw(&self) -> u64 {
99        self.handle.as_raw()
100    }
101}
102
103impl Drop for RenderPass {
104    fn drop(&mut self) {
105        unsafe {
106            self.device
107                .inner()
108                .destroy_render_pass(self.handle, ALLOCATION_CALLBACK_NONE);
109        }
110    }
111}
112
113#[derive(Debug, Default, Clone)]
114pub struct RenderPassProperties {
115    pub attachment_descriptions: Vec<vk::AttachmentDescription>,
116    pub subpasses: Vec<Subpass>,
117    pub subpass_dependencies: Vec<vk::SubpassDependency>,
118}
119
120impl RenderPassProperties {
121    /// Safety:
122    ///
123    /// For each subpass:
124    /// - if `subpass_description.p_color_attachments` is not null it must point to an array with
125    ///   `subpass_description.color_attachment_count` many elements.
126    /// - if `subpass_description.p_input_attachments` is not null it must point to an array with
127    ///   `subpass_description.input_attachment_count` many elements.
128    pub unsafe fn from_create_info_builder(
129        create_info_builder: &vk::RenderPassCreateInfoBuilder,
130    ) -> Self {
131        let mut attachment_descriptions = Vec::<vk::AttachmentDescription>::new();
132        if create_info_builder.p_attachments != std::ptr::null() {
133            for i in 0..create_info_builder.attachment_count {
134                let vk_attachment =
135                    unsafe { *create_info_builder.p_attachments.offset(i as isize) };
136                attachment_descriptions.push(vk_attachment);
137            }
138        }
139
140        let mut subpasses = Vec::<Subpass>::new();
141        if create_info_builder.p_subpasses != std::ptr::null() {
142            for i in 0..create_info_builder.subpass_count {
143                let vk_subpass = unsafe { *create_info_builder.p_subpasses.offset(i as isize) };
144                let subpass = unsafe { Subpass::from_subpass_description(&vk_subpass) };
145                subpasses.push(subpass);
146            }
147        }
148
149        let mut subpass_dependencies = Vec::<vk::SubpassDependency>::new();
150        if create_info_builder.p_dependencies != std::ptr::null() {
151            for i in 0..create_info_builder.dependency_count {
152                let vk_dependency =
153                    unsafe { *create_info_builder.p_dependencies.offset(i as isize) };
154                subpass_dependencies.push(vk_dependency);
155            }
156        }
157
158        Self {
159            attachment_descriptions,
160            subpasses,
161            subpass_dependencies,
162        }
163    }
164}
165
166#[derive(Debug, Default, Clone)]
167pub struct Subpass {
168    pub color_attachments: Vec<vk::AttachmentReference>,
169    pub depth_attachment: Option<vk::AttachmentReference>,
170    pub input_attachments: Vec<vk::AttachmentReference>,
171}
172
173impl Subpass {
174    pub fn new(
175        color_attachments: &[vk::AttachmentReference],
176        depth_attachment: Option<vk::AttachmentReference>,
177        input_attachments: &[vk::AttachmentReference],
178    ) -> Self {
179        Self {
180            color_attachments: color_attachments.into(),
181            depth_attachment,
182            input_attachments: input_attachments.into(),
183        }
184    }
185
186    pub fn from_subpass_description_builder(
187        subpass_description: &vk::SubpassDescriptionBuilder,
188    ) -> Self {
189        unsafe { Self::from_subpass_description(&*subpass_description) }
190    }
191
192    /// Safety:
193    ///
194    /// - if `subpass_description.p_color_attachments` is not null it must point to an array with
195    ///   `subpass_description.color_attachment_count` many elements.
196    /// - if `subpass_description.p_input_attachments` is not null it must point to an array with
197    ///   `subpass_description.input_attachment_count` many elements.
198    pub unsafe fn from_subpass_description(subpass_description: &vk::SubpassDescription) -> Self {
199        let mut color_attachments = Vec::<vk::AttachmentReference>::new();
200        if subpass_description.p_color_attachments != std::ptr::null() {
201            for i in 0..subpass_description.color_attachment_count {
202                let vk_attachment =
203                    unsafe { *subpass_description.p_color_attachments.offset(i as isize) };
204                color_attachments.push(vk_attachment);
205            }
206        }
207
208        let depth_attachment: Option<vk::AttachmentReference> =
209            if subpass_description.p_depth_stencil_attachment != std::ptr::null() {
210                let vk_attachment = *subpass_description.p_depth_stencil_attachment;
211                Some(vk_attachment)
212            } else {
213                None
214            };
215
216        let mut input_attachments = Vec::<vk::AttachmentReference>::new();
217        if subpass_description.p_input_attachments != std::ptr::null() {
218            for i in 0..subpass_description.input_attachment_count {
219                let vk_attachment =
220                    unsafe { *subpass_description.p_input_attachments.offset(i as isize) };
221                input_attachments.push(vk_attachment);
222            }
223        }
224
225        Self {
226            color_attachments,
227            depth_attachment,
228            input_attachments,
229        }
230    }
231
232    pub fn subpass_description_builder(&self) -> vk::SubpassDescriptionBuilder {
233        let mut subpass_description_builder =
234            vk::SubpassDescription::builder().pipeline_bind_point(vk::PipelineBindPoint::GRAPHICS);
235
236        if self.color_attachments.len() > 0 {
237            subpass_description_builder =
238                subpass_description_builder.color_attachments(&self.color_attachments);
239        }
240        if self.input_attachments.len() > 0 {
241            subpass_description_builder =
242                subpass_description_builder.input_attachments(&self.input_attachments);
243        }
244        if let Some(depth_attachment) = &self.depth_attachment {
245            subpass_description_builder =
246                subpass_description_builder.depth_stencil_attachment(depth_attachment);
247        }
248
249        subpass_description_builder
250    }
251}