duku/pipeline/
render_pass.rs1use std::ptr;
7
8use super::Attachment;
9use super::Clear;
10use super::ShaderConfig;
11use super::Store;
12use crate::device::Device;
13use crate::image::Format;
14use crate::image::ImageLayout;
15use crate::image::Msaa;
16use crate::vk;
17
18pub(crate) struct RenderPass {
19 handle: vk::RenderPass,
20 attachments: Vec<Attachment>,
21}
22
23impl RenderPass {
24 pub(crate) fn new(device: &Device, config: ShaderConfig, present: bool) -> Self {
25 let multisampled = config.msaa != Msaa::Disabled;
26 let only_depth = config.outputs == 0;
27
28 let mut attachment_descriptions = vec![];
29 let mut attachments = vec![];
30
31 let layout = if only_depth {
33 ImageLayout::ShaderDepth
34 } else {
35 ImageLayout::Depth
36 };
37
38 let a = Attachment::new(
39 attachments.len() as u32,
40 layout,
41 Format::Depth,
42 config.msaa,
43 Clear::Enabled,
44 Store::from(only_depth),
45 );
46
47 let depth_attachment = a.reference();
48 attachment_descriptions.push(a.description());
49 attachments.push(a);
50
51 let mut color_attachments = vec![];
53 let mut resolve_attachments = vec![];
54 for _ in 0..config.outputs {
55 let layout = if present {
57 ImageLayout::Present
58 } else {
59 ImageLayout::ShaderColor
60 };
61
62 let a = Attachment::new(
63 attachments.len() as u32,
64 layout,
65 Format::Bgra,
66 Msaa::Disabled,
67 Clear::from(!multisampled),
68 Store::Enabled,
69 );
70
71 if multisampled {
72 resolve_attachments.push(a.reference());
73 } else {
74 color_attachments.push(a.reference());
75 }
76 attachment_descriptions.push(a.description());
77 attachments.push(a);
78
79 if multisampled {
81 let a_msaa = Attachment::new(
82 attachments.len() as u32,
83 ImageLayout::Color,
84 Format::Bgra,
85 config.msaa,
86 Clear::Enabled,
87 Store::Disabled,
88 );
89
90 color_attachments.push(a_msaa.reference());
91 attachment_descriptions.push(a_msaa.description());
92 attachments.push(a_msaa);
93 }
94 }
95
96 let dependencies = if only_depth {
98 [
100 vk::SubpassDependency {
102 src_subpass: vk::SUBPASS_EXTERNAL,
103 dst_subpass: 0,
104 src_stage_mask: vk::PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
105 dst_stage_mask: vk::PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
106 src_access_mask: 0,
107 dst_access_mask: vk::ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
108 dependency_flags: vk::DEPENDENCY_BY_REGION_BIT,
109 },
110 vk::SubpassDependency {
112 src_subpass: 0,
113 dst_subpass: vk::SUBPASS_EXTERNAL,
114 src_stage_mask: vk::PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
115 dst_stage_mask: vk::PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
116 src_access_mask: vk::ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
117 dst_access_mask: 0,
118 dependency_flags: vk::DEPENDENCY_BY_REGION_BIT,
119 },
120 ]
121 } else {
122 [
124 vk::SubpassDependency {
126 src_subpass: vk::SUBPASS_EXTERNAL,
127 dst_subpass: 0,
128 src_stage_mask: vk::PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
129 dst_stage_mask: vk::PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
130 src_access_mask: 0,
131 dst_access_mask: vk::ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
132 dependency_flags: vk::DEPENDENCY_BY_REGION_BIT,
133 },
134 vk::SubpassDependency {
136 src_subpass: 0,
137 dst_subpass: vk::SUBPASS_EXTERNAL,
138 src_stage_mask: vk::PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
139 dst_stage_mask: vk::PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
140 src_access_mask: vk::ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
141 dst_access_mask: 0,
142 dependency_flags: vk::DEPENDENCY_BY_REGION_BIT,
143 },
144 ]
145 };
146
147 let mut subpass = [vk::SubpassDescription {
149 flags: 0,
150 pipeline_bind_point: vk::PIPELINE_BIND_POINT_GRAPHICS,
151 input_attachment_count: 0,
152 p_input_attachments: ptr::null(),
153 color_attachment_count: 0,
154 p_color_attachments: ptr::null(),
155 p_resolve_attachments: ptr::null(),
156 p_depth_stencil_attachment: &depth_attachment,
157 preserve_attachment_count: 0,
158 p_preserve_attachments: ptr::null(),
159 }];
160
161 if !color_attachments.is_empty() {
162 subpass[0].color_attachment_count = color_attachments.len() as u32;
163 subpass[0].p_color_attachments = color_attachments.as_ptr();
164 }
165 if !resolve_attachments.is_empty() {
166 subpass[0].p_resolve_attachments = resolve_attachments.as_ptr();
167 }
168
169 let info = vk::RenderPassCreateInfo {
170 s_type: vk::STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
171 p_next: ptr::null(),
172 flags: 0,
173 attachment_count: attachment_descriptions.len() as u32,
174 p_attachments: attachment_descriptions.as_ptr(),
175 subpass_count: subpass.len() as u32,
176 p_subpasses: subpass.as_ptr(),
177 dependency_count: dependencies.len() as u32,
178 p_dependencies: dependencies.as_ptr(),
179 };
180
181 let handle = device.create_render_pass(&info);
182
183 Self {
184 attachments,
185 handle,
186 }
187 }
188
189 pub(crate) fn destroy(&self, device: &Device) {
190 device.destroy_render_pass(self.handle);
191 }
192
193 pub(crate) fn attachments(&self) -> impl Iterator<Item = &Attachment> {
194 self.attachments.iter()
195 }
196
197 pub(crate) const fn handle(&self) -> vk::RenderPass {
198 self.handle
199 }
200}