1use crate::device::Device;
10use crate::enums::*;
11use crate::error::{Error, Result};
12use crate::types::*;
13
14#[doc = crate::spec_link!("render pass", "8", "renderpass")]
16#[derive(Debug)]
17pub struct RenderPass {
18 handle: Handle<VkRenderPass>,
19 compat: RenderPassCompat,
20 pub(crate) device: Arc<Device>,
21}
22
23impl RenderPass {
24 #[doc = crate::man_link!(vkCreateRenderPass)]
25 pub fn new(
26 device: &Arc<Device>, info: &RenderPassCreateInfo,
27 ) -> Result<Arc<Self>> {
28 for subpass in info.subpasses {
29 if subpass.color_attachments.len()
30 > device.limits().max_color_attachments
31 {
32 return Err(Error::LimitExceeded);
33 }
34 }
35 let compat = RenderPassCompat::new(info)?;
36 let mut handle = None;
37 unsafe {
38 (device.fun.create_render_pass)(
39 device.handle(),
40 info,
41 None,
42 &mut handle,
43 )?;
44 }
45 let handle = handle.unwrap();
46 Ok(Arc::new(Self { handle, compat, device: device.clone() }))
47 }
48
49 pub fn handle(&self) -> Ref<VkRenderPass> {
51 self.handle.borrow()
52 }
53 pub fn num_subpasses(&self) -> u32 {
55 self.compat.subpasses.len() as u32
56 }
57 pub fn device(&self) -> &Arc<Device> {
59 &self.device
60 }
61 pub fn compatible(&self, other: &Self) -> bool {
63 std::ptr::eq(self, other) || self.compat == other.compat
64 }
65}
66
67impl Drop for RenderPass {
68 fn drop(&mut self) {
69 unsafe {
70 (self.device.fun.destroy_render_pass)(
71 self.device.handle(),
72 self.handle.borrow_mut(),
73 None,
74 )
75 }
76 }
77}
78
79#[derive(Debug, PartialEq, Eq)]
80struct AttachmentRefCompat {
81 format: Format,
82 samples: SampleCount,
83}
84
85#[derive(Debug, Eq)]
86struct SubpassCompat {
87 input_attachments: Vec<Option<AttachmentRefCompat>>,
88 color_attachments: Vec<Option<AttachmentRefCompat>>,
89 resolve_attachments: Vec<Option<AttachmentRefCompat>>,
90 depth_stencil_attachments: Vec<Option<AttachmentRefCompat>>,
91 preserve_attachments: Vec<Option<AttachmentRefCompat>>,
92}
93
94#[derive(Debug, PartialEq, Eq)]
95struct RenderPassCompat {
96 subpasses: Vec<SubpassCompat>,
97 dependencies: Vec<SubpassDependency>,
98}
99
100fn flatten_ref<T>(opt: Option<&Option<T>>) -> Option<&T> {
101 match opt {
102 Some(Some(v)) => Some(v),
103 _ => None,
104 }
105}
106
107fn att_ref_array_compat(
108 a: &[Option<AttachmentRefCompat>], b: &[Option<AttachmentRefCompat>],
109) -> bool {
110 for i in 0..a.len().max(b.len()) {
111 if flatten_ref(a.get(i)) != flatten_ref(b.get(i)) {
112 return false;
113 }
114 }
115 true
116}
117
118impl PartialEq for SubpassCompat {
119 fn eq(&self, other: &Self) -> bool {
120 att_ref_array_compat(&self.input_attachments, &other.input_attachments)
121 && att_ref_array_compat(
122 &self.color_attachments,
123 &other.color_attachments,
124 )
125 && att_ref_array_compat(
126 &self.resolve_attachments,
127 &other.resolve_attachments,
128 )
129 && att_ref_array_compat(
130 &self.depth_stencil_attachments,
131 &other.depth_stencil_attachments,
132 )
133 && att_ref_array_compat(
134 &self.preserve_attachments,
135 &other.preserve_attachments,
136 )
137 }
138}
139
140impl RenderPassCompat {
141 fn new(info: &RenderPassCreateInfo) -> Result<Self> {
142 let att_ref = |att: &AttachmentReference| {
143 if att.attachment == u32::MAX {
144 Ok(None)
145 } else if let Some(desc) =
146 info.attachments.as_slice().get(att.attachment as usize)
147 {
148 Ok(Some(AttachmentRefCompat {
149 format: desc.format,
150 samples: desc.samples,
151 }))
152 } else {
153 Err(Error::OutOfBounds)
154 }
155 };
156 let mut subpasses = vec![];
157 for subpass in info.subpasses {
158 subpasses.push(SubpassCompat {
159 input_attachments: subpass
160 .input_attachments
161 .into_iter()
162 .map(att_ref)
163 .collect::<Result<_>>()?,
164 preserve_attachments: subpass
165 .color_attachments
166 .into_iter()
167 .map(att_ref)
168 .collect::<Result<_>>()?,
169 color_attachments: subpass
170 .color_attachments
171 .into_iter()
172 .map(att_ref)
173 .collect::<Result<_>>()?,
174 resolve_attachments: subpass
175 .resolve_attachments
176 .map_or(Default::default(), |a| unsafe {
177 a.as_slice(subpass.color_attachments.len())
178 })
179 .iter()
180 .map(att_ref)
181 .collect::<Result<_>>()?,
182 depth_stencil_attachments: subpass
183 .depth_stencil_attachments
184 .map_or(Default::default(), |a| unsafe {
185 a.as_slice(subpass.color_attachments.len())
186 })
187 .iter()
188 .map(att_ref)
189 .collect::<Result<_>>()?,
190 });
191 }
192
193 Ok(Self {
194 subpasses,
195 dependencies: info.dependencies.into_iter().cloned().collect(),
196 })
197 }
198}