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 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 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 #[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 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 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}