1 // Copyright (c) 2022 The vulkano developers
2 // Licensed under the Apache License, Version 2.0
3 // <LICENSE-APACHE or
4 // https://www.apache.org/licenses/LICENSE-2.0> or the MIT
5 // license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
6 // at your option. All files in the project carrying such
7 // notice may not be copied, modified, or distributed except
8 // according to those terms.
9 
10 use crate::{
11     command_buffer::{
12         allocator::CommandBufferAllocator,
13         auto::{
14             BeginRenderPassState, BeginRenderingAttachments, BeginRenderingState, RenderPassState,
15             RenderPassStateType,
16         },
17         synced::{Command, Resource, SyncCommandBufferBuilder, SyncCommandBufferBuilderError},
18         sys::UnsafeCommandBufferBuilder,
19         AutoCommandBufferBuilder, ResourceInCommand, ResourceUseRef, SubpassContents,
20     },
21     device::{DeviceOwned, QueueFlags},
22     format::{ClearColorValue, ClearValue, Format, NumericType},
23     image::{ImageAspects, ImageLayout, ImageUsage, ImageViewAbstract, SampleCount},
24     render_pass::{
25         AttachmentDescription, Framebuffer, LoadOp, RenderPass, ResolveMode, StoreOp,
26         SubpassDescription,
27     },
28     sync::{AccessFlags, PipelineMemoryAccess, PipelineStages},
29     RequirementNotMet, RequiresOneOf, Version, VulkanObject,
30 };
31 use smallvec::SmallVec;
32 use std::{
33     cmp::min,
34     error::Error,
35     fmt::{Display, Error as FmtError, Formatter},
36     ops::Range,
37     sync::Arc,
38 };
39 
40 /// # Commands for render passes.
41 ///
42 /// These commands require a graphics queue.
43 impl<L, A> AutoCommandBufferBuilder<L, A>
44 where
45     A: CommandBufferAllocator,
46 {
47     /// Begins a render pass using a render pass object and framebuffer.
48     ///
49     /// You must call this or `begin_rendering` before you can record draw commands.
50     ///
51     /// `contents` specifies what kinds of commands will be recorded in the render pass, either
52     /// draw commands or executions of secondary command buffers.
begin_render_pass( &mut self, mut render_pass_begin_info: RenderPassBeginInfo, contents: SubpassContents, ) -> Result<&mut Self, RenderPassError>53     pub fn begin_render_pass(
54         &mut self,
55         mut render_pass_begin_info: RenderPassBeginInfo,
56         contents: SubpassContents,
57     ) -> Result<&mut Self, RenderPassError> {
58         self.validate_begin_render_pass(&mut render_pass_begin_info, contents)?;
59 
60         unsafe {
61             let RenderPassBeginInfo {
62                 ref render_pass,
63                 ref framebuffer,
64                 render_area_offset,
65                 render_area_extent,
66                 clear_values: _,
67                 _ne: _,
68             } = render_pass_begin_info;
69 
70             let subpass = render_pass.clone().first_subpass();
71             let view_mask = subpass.subpass_desc().view_mask;
72 
73             let render_pass_state = RenderPassState {
74                 contents,
75                 render_area_offset,
76                 render_area_extent,
77                 render_pass: BeginRenderPassState {
78                     subpass,
79                     framebuffer: Some(framebuffer.clone()),
80                 }
81                 .into(),
82                 view_mask,
83             };
84 
85             self.inner
86                 .begin_render_pass(render_pass_begin_info, contents)?;
87             self.render_pass_state = Some(render_pass_state);
88 
89             Ok(self)
90         }
91     }
92 
validate_begin_render_pass( &self, render_pass_begin_info: &mut RenderPassBeginInfo, contents: SubpassContents, ) -> Result<(), RenderPassError>93     fn validate_begin_render_pass(
94         &self,
95         render_pass_begin_info: &mut RenderPassBeginInfo,
96         contents: SubpassContents,
97     ) -> Result<(), RenderPassError> {
98         let device = self.device();
99 
100         // VUID-VkSubpassBeginInfo-contents-parameter
101         contents.validate_device(device)?;
102 
103         let queue_family_properties = self.queue_family_properties();
104 
105         // VUID-vkCmdBeginRenderPass2-commandBuffer-cmdpool
106         if !queue_family_properties
107             .queue_flags
108             .intersects(QueueFlags::GRAPHICS)
109         {
110             return Err(RenderPassError::NotSupportedByQueueFamily);
111         }
112 
113         // VUID-vkCmdBeginRenderPass2-renderpass
114         if self.render_pass_state.is_some() {
115             return Err(RenderPassError::ForbiddenInsideRenderPass);
116         }
117 
118         let RenderPassBeginInfo {
119             render_pass,
120             framebuffer,
121             render_area_offset,
122             render_area_extent,
123             clear_values,
124             _ne: _,
125         } = render_pass_begin_info;
126 
127         // VUID-VkRenderPassBeginInfo-commonparent
128         // VUID-vkCmdBeginRenderPass2-framebuffer-02779
129         assert_eq!(device, framebuffer.device());
130 
131         // VUID-VkRenderPassBeginInfo-renderPass-00904
132         if !render_pass.is_compatible_with(framebuffer.render_pass()) {
133             return Err(RenderPassError::FramebufferNotCompatible);
134         }
135 
136         for i in 0..2 {
137             // VUID-VkRenderPassBeginInfo-pNext-02852
138             // VUID-VkRenderPassBeginInfo-pNext-02853
139             if render_area_offset[i] + render_area_extent[i] > framebuffer.extent()[i] {
140                 return Err(RenderPassError::RenderAreaOutOfBounds);
141             }
142         }
143 
144         for (attachment_index, (attachment_desc, image_view)) in render_pass
145             .attachments()
146             .iter()
147             .zip(framebuffer.attachments())
148             .enumerate()
149         {
150             let attachment_index = attachment_index as u32;
151             let &AttachmentDescription {
152                 initial_layout,
153                 final_layout,
154                 ..
155             } = attachment_desc;
156 
157             for layout in [initial_layout, final_layout] {
158                 match layout {
159                     ImageLayout::ColorAttachmentOptimal => {
160                         // VUID-vkCmdBeginRenderPass2-initialLayout-03094
161                         if !image_view.usage().intersects(ImageUsage::COLOR_ATTACHMENT) {
162                             return Err(RenderPassError::AttachmentImageMissingUsage {
163                                 attachment_index,
164                                 usage: "color_attachment",
165                             });
166                         }
167                     }
168                     ImageLayout::DepthReadOnlyStencilAttachmentOptimal
169                     | ImageLayout::DepthAttachmentStencilReadOnlyOptimal
170                     | ImageLayout::DepthStencilAttachmentOptimal
171                     | ImageLayout::DepthStencilReadOnlyOptimal => {
172                         // VUID-vkCmdBeginRenderPass2-initialLayout-03096
173                         if !image_view
174                             .usage()
175                             .intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
176                         {
177                             return Err(RenderPassError::AttachmentImageMissingUsage {
178                                 attachment_index,
179                                 usage: "depth_stencil_attachment",
180                             });
181                         }
182                     }
183                     ImageLayout::ShaderReadOnlyOptimal => {
184                         // VUID-vkCmdBeginRenderPass2-initialLayout-03097
185                         if !image_view
186                             .usage()
187                             .intersects(ImageUsage::SAMPLED | ImageUsage::INPUT_ATTACHMENT)
188                         {
189                             return Err(RenderPassError::AttachmentImageMissingUsage {
190                                 attachment_index,
191                                 usage: "sampled or input_attachment",
192                             });
193                         }
194                     }
195                     ImageLayout::TransferSrcOptimal => {
196                         // VUID-vkCmdBeginRenderPass2-initialLayout-03098
197                         if !image_view.usage().intersects(ImageUsage::TRANSFER_SRC) {
198                             return Err(RenderPassError::AttachmentImageMissingUsage {
199                                 attachment_index,
200                                 usage: "transfer_src",
201                             });
202                         }
203                     }
204                     ImageLayout::TransferDstOptimal => {
205                         // VUID-vkCmdBeginRenderPass2-initialLayout-03099
206                         if !image_view.usage().intersects(ImageUsage::TRANSFER_DST) {
207                             return Err(RenderPassError::AttachmentImageMissingUsage {
208                                 attachment_index,
209                                 usage: "transfer_dst",
210                             });
211                         }
212                     }
213                     _ => (),
214                 }
215             }
216         }
217 
218         for subpass_desc in render_pass.subpasses() {
219             let SubpassDescription {
220                 view_mask: _,
221                 input_attachments,
222                 color_attachments,
223                 resolve_attachments,
224                 depth_stencil_attachment,
225                 preserve_attachments: _,
226                 _ne: _,
227             } = subpass_desc;
228 
229             for atch_ref in (input_attachments.iter())
230                 .chain(color_attachments)
231                 .chain(resolve_attachments)
232                 .chain([depth_stencil_attachment])
233                 .flatten()
234             {
235                 let image_view = &framebuffer.attachments()[atch_ref.attachment as usize];
236 
237                 match atch_ref.layout {
238                     ImageLayout::ColorAttachmentOptimal => {
239                         // VUID-vkCmdBeginRenderPass2-initialLayout-03094
240                         if !image_view.usage().intersects(ImageUsage::COLOR_ATTACHMENT) {
241                             return Err(RenderPassError::AttachmentImageMissingUsage {
242                                 attachment_index: atch_ref.attachment,
243                                 usage: "color_attachment",
244                             });
245                         }
246                     }
247                     ImageLayout::DepthReadOnlyStencilAttachmentOptimal
248                     | ImageLayout::DepthAttachmentStencilReadOnlyOptimal
249                     | ImageLayout::DepthStencilAttachmentOptimal
250                     | ImageLayout::DepthStencilReadOnlyOptimal => {
251                         // VUID-vkCmdBeginRenderPass2-initialLayout-03096
252                         if !image_view
253                             .usage()
254                             .intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
255                         {
256                             return Err(RenderPassError::AttachmentImageMissingUsage {
257                                 attachment_index: atch_ref.attachment,
258                                 usage: "depth_stencil_attachment",
259                             });
260                         }
261                     }
262                     ImageLayout::ShaderReadOnlyOptimal => {
263                         // VUID-vkCmdBeginRenderPass2-initialLayout-03097
264                         if !image_view
265                             .usage()
266                             .intersects(ImageUsage::SAMPLED | ImageUsage::INPUT_ATTACHMENT)
267                         {
268                             return Err(RenderPassError::AttachmentImageMissingUsage {
269                                 attachment_index: atch_ref.attachment,
270                                 usage: "sampled or input_attachment",
271                             });
272                         }
273                     }
274                     ImageLayout::TransferSrcOptimal => {
275                         // VUID-vkCmdBeginRenderPass2-initialLayout-03098
276                         if !image_view.usage().intersects(ImageUsage::TRANSFER_SRC) {
277                             return Err(RenderPassError::AttachmentImageMissingUsage {
278                                 attachment_index: atch_ref.attachment,
279                                 usage: "transfer_src",
280                             });
281                         }
282                     }
283                     ImageLayout::TransferDstOptimal => {
284                         // VUID-vkCmdBeginRenderPass2-initialLayout-03099
285                         if !image_view.usage().intersects(ImageUsage::TRANSFER_DST) {
286                             return Err(RenderPassError::AttachmentImageMissingUsage {
287                                 attachment_index: atch_ref.attachment,
288                                 usage: "transfer_dst",
289                             });
290                         }
291                     }
292                     _ => (),
293                 }
294             }
295         }
296 
297         // VUID-VkRenderPassBeginInfo-clearValueCount-00902
298         if clear_values.len() < render_pass.attachments().len() {
299             return Err(RenderPassError::ClearValueMissing {
300                 attachment_index: clear_values.len() as u32,
301             });
302         }
303 
304         // VUID-VkRenderPassBeginInfo-clearValueCount-04962
305         for (attachment_index, (attachment_desc, &mut clear_value)) in render_pass
306             .attachments()
307             .iter()
308             .zip(clear_values)
309             .enumerate()
310         {
311             let attachment_index = attachment_index as u32;
312             let attachment_format = attachment_desc.format.unwrap();
313 
314             if attachment_desc.load_op == LoadOp::Clear
315                 || attachment_desc.stencil_load_op == LoadOp::Clear
316             {
317                 let clear_value = match clear_value {
318                     Some(x) => x,
319                     None => return Err(RenderPassError::ClearValueMissing { attachment_index }),
320                 };
321 
322                 if let (Some(numeric_type), LoadOp::Clear) =
323                     (attachment_format.type_color(), attachment_desc.load_op)
324                 {
325                     match numeric_type {
326                         NumericType::SFLOAT
327                         | NumericType::UFLOAT
328                         | NumericType::SNORM
329                         | NumericType::UNORM
330                         | NumericType::SSCALED
331                         | NumericType::USCALED
332                         | NumericType::SRGB => {
333                             if !matches!(clear_value, ClearValue::Float(_)) {
334                                 return Err(RenderPassError::ClearValueNotCompatible {
335                                     clear_value,
336                                     attachment_index,
337                                     attachment_format,
338                                 });
339                             }
340                         }
341                         NumericType::SINT => {
342                             if !matches!(clear_value, ClearValue::Int(_)) {
343                                 return Err(RenderPassError::ClearValueNotCompatible {
344                                     clear_value,
345                                     attachment_index,
346                                     attachment_format,
347                                 });
348                             }
349                         }
350                         NumericType::UINT => {
351                             if !matches!(clear_value, ClearValue::Uint(_)) {
352                                 return Err(RenderPassError::ClearValueNotCompatible {
353                                     clear_value,
354                                     attachment_index,
355                                     attachment_format,
356                                 });
357                             }
358                         }
359                     }
360                 } else {
361                     let attachment_aspects = attachment_format.aspects();
362                     let need_depth = attachment_aspects.intersects(ImageAspects::DEPTH)
363                         && attachment_desc.load_op == LoadOp::Clear;
364                     let need_stencil = attachment_aspects.intersects(ImageAspects::STENCIL)
365                         && attachment_desc.stencil_load_op == LoadOp::Clear;
366 
367                     if need_depth && need_stencil {
368                         if !matches!(clear_value, ClearValue::DepthStencil(_)) {
369                             return Err(RenderPassError::ClearValueNotCompatible {
370                                 clear_value,
371                                 attachment_index,
372                                 attachment_format,
373                             });
374                         }
375                     } else if need_depth {
376                         if !matches!(clear_value, ClearValue::Depth(_)) {
377                             return Err(RenderPassError::ClearValueNotCompatible {
378                                 clear_value,
379                                 attachment_index,
380                                 attachment_format,
381                             });
382                         }
383                     } else if need_stencil {
384                         if !matches!(clear_value, ClearValue::Stencil(_)) {
385                             return Err(RenderPassError::ClearValueNotCompatible {
386                                 clear_value,
387                                 attachment_index,
388                                 attachment_format,
389                             });
390                         }
391                     }
392                 }
393             }
394         }
395 
396         // VUID-vkCmdBeginRenderPass2-initialLayout-03100
397         // TODO:
398 
399         // VUID-vkCmdBeginRenderPass2-srcStageMask-06453
400         // TODO:
401 
402         // VUID-vkCmdBeginRenderPass2-dstStageMask-06454
403         // TODO:
404 
405         // VUID-vkCmdBeginRenderPass2-framebuffer-02533
406         // For any attachment in framebuffer that is used by renderPass and is bound to memory locations that are also bound to another attachment used by renderPass, and if at least one of those uses causes either
407         // attachment to be written to, both attachments must have had the VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT set
408 
409         Ok(())
410     }
411 
412     /// Advances to the next subpass of the render pass previously begun with `begin_render_pass`.
next_subpass( &mut self, contents: SubpassContents, ) -> Result<&mut Self, RenderPassError>413     pub fn next_subpass(
414         &mut self,
415         contents: SubpassContents,
416     ) -> Result<&mut Self, RenderPassError> {
417         self.validate_next_subpass(contents)?;
418 
419         unsafe {
420             let render_pass_state = self.render_pass_state.as_mut().unwrap();
421             let begin_render_pass_state = match &mut render_pass_state.render_pass {
422                 RenderPassStateType::BeginRenderPass(x) => x,
423                 _ => unreachable!(),
424             };
425 
426             begin_render_pass_state.subpass.next_subpass();
427             render_pass_state.contents = contents;
428             render_pass_state.view_mask = begin_render_pass_state.subpass.subpass_desc().view_mask;
429 
430             if render_pass_state.view_mask != 0 {
431                 // When multiview is enabled, at the beginning of each subpass, all
432                 // non-render pass state is undefined.
433                 self.inner.reset_state();
434             }
435 
436             self.inner.next_subpass(contents);
437         }
438 
439         Ok(self)
440     }
441 
validate_next_subpass(&self, contents: SubpassContents) -> Result<(), RenderPassError>442     fn validate_next_subpass(&self, contents: SubpassContents) -> Result<(), RenderPassError> {
443         let device = self.device();
444 
445         // VUID-VkSubpassBeginInfo-contents-parameter
446         contents.validate_device(device)?;
447 
448         // VUID-vkCmdNextSubpass2-renderpass
449         let render_pass_state = self
450             .render_pass_state
451             .as_ref()
452             .ok_or(RenderPassError::ForbiddenOutsideRenderPass)?;
453 
454         let begin_render_pass_state = match &render_pass_state.render_pass {
455             RenderPassStateType::BeginRenderPass(state) => state,
456             RenderPassStateType::BeginRendering(_) => {
457                 return Err(RenderPassError::ForbiddenWithBeginRendering)
458             }
459         };
460 
461         // VUID-vkCmdNextSubpass2-None-03102
462         if begin_render_pass_state.subpass.is_last_subpass() {
463             return Err(RenderPassError::NoSubpassesRemaining {
464                 current_subpass: begin_render_pass_state.subpass.index(),
465             });
466         }
467 
468         // VUID?
469         if self.query_state.values().any(|state| state.in_subpass) {
470             return Err(RenderPassError::QueryIsActive);
471         }
472 
473         // VUID-vkCmdNextSubpass2-commandBuffer-cmdpool
474         debug_assert!(self
475             .queue_family_properties()
476             .queue_flags
477             .intersects(QueueFlags::GRAPHICS));
478 
479         // VUID-vkCmdNextSubpass2-bufferlevel
480         // Ensured by the type of the impl block
481 
482         Ok(())
483     }
484 
485     /// Ends the render pass previously begun with `begin_render_pass`.
486     ///
487     /// This must be called after you went through all the subpasses.
end_render_pass(&mut self) -> Result<&mut Self, RenderPassError>488     pub fn end_render_pass(&mut self) -> Result<&mut Self, RenderPassError> {
489         self.validate_end_render_pass()?;
490 
491         unsafe {
492             self.inner.end_render_pass();
493             self.render_pass_state = None;
494         }
495 
496         Ok(self)
497     }
498 
validate_end_render_pass(&self) -> Result<(), RenderPassError>499     fn validate_end_render_pass(&self) -> Result<(), RenderPassError> {
500         // VUID-vkCmdEndRenderPass2-renderpass
501         let render_pass_state = self
502             .render_pass_state
503             .as_ref()
504             .ok_or(RenderPassError::ForbiddenOutsideRenderPass)?;
505 
506         let begin_render_pass_state = match &render_pass_state.render_pass {
507             RenderPassStateType::BeginRenderPass(state) => state,
508             RenderPassStateType::BeginRendering(_) => {
509                 return Err(RenderPassError::ForbiddenWithBeginRendering)
510             }
511         };
512 
513         // VUID-vkCmdEndRenderPass2-None-03103
514         if !begin_render_pass_state.subpass.is_last_subpass() {
515             return Err(RenderPassError::SubpassesRemaining {
516                 current_subpass: begin_render_pass_state.subpass.index(),
517                 remaining_subpasses: begin_render_pass_state
518                     .subpass
519                     .render_pass()
520                     .subpasses()
521                     .len() as u32
522                     - begin_render_pass_state.subpass.index(),
523             });
524         }
525 
526         // VUID?
527         if self.query_state.values().any(|state| state.in_subpass) {
528             return Err(RenderPassError::QueryIsActive);
529         }
530 
531         // VUID-vkCmdEndRenderPass2-commandBuffer-cmdpool
532         debug_assert!(self
533             .queue_family_properties()
534             .queue_flags
535             .intersects(QueueFlags::GRAPHICS));
536 
537         // VUID-vkCmdEndRenderPass2-bufferlevel
538         // Ensured by the type of the impl block
539 
540         Ok(())
541     }
542 }
543 
544 impl<L, A> AutoCommandBufferBuilder<L, A>
545 where
546     A: CommandBufferAllocator,
547 {
548     /// Begins a render pass without a render pass object or framebuffer.
549     ///
550     /// You must call this or `begin_render_pass` before you can record draw commands.
begin_rendering( &mut self, mut rendering_info: RenderingInfo, ) -> Result<&mut Self, RenderPassError>551     pub fn begin_rendering(
552         &mut self,
553         mut rendering_info: RenderingInfo,
554     ) -> Result<&mut Self, RenderPassError> {
555         rendering_info.set_extent_layers()?;
556         self.validate_begin_rendering(&mut rendering_info)?;
557 
558         unsafe {
559             let RenderingInfo {
560                 render_area_offset,
561                 render_area_extent,
562                 layer_count: _,
563                 view_mask,
564                 ref color_attachments,
565                 ref depth_attachment,
566                 ref stencil_attachment,
567                 contents,
568                 _ne: _,
569             } = rendering_info;
570 
571             let render_pass_state = RenderPassState {
572                 contents,
573                 render_area_offset,
574                 render_area_extent,
575                 render_pass: BeginRenderingState {
576                     attachments: Some(BeginRenderingAttachments {
577                         color_attachments: color_attachments.clone(),
578                         depth_attachment: depth_attachment.clone(),
579                         stencil_attachment: stencil_attachment.clone(),
580                     }),
581                     color_attachment_formats: color_attachments
582                         .iter()
583                         .map(|a| a.as_ref().map(|a| a.image_view.format().unwrap()))
584                         .collect(),
585                     depth_attachment_format: depth_attachment
586                         .as_ref()
587                         .map(|a| a.image_view.format().unwrap()),
588                     stencil_attachment_format: stencil_attachment
589                         .as_ref()
590                         .map(|a| a.image_view.format().unwrap()),
591                     pipeline_used: false,
592                 }
593                 .into(),
594                 view_mask,
595             };
596 
597             self.inner.begin_rendering(rendering_info)?;
598 
599             self.render_pass_state = Some(render_pass_state);
600         }
601 
602         Ok(self)
603     }
604 
validate_begin_rendering( &self, rendering_info: &mut RenderingInfo, ) -> Result<(), RenderPassError>605     fn validate_begin_rendering(
606         &self,
607         rendering_info: &mut RenderingInfo,
608     ) -> Result<(), RenderPassError> {
609         let device = self.device();
610         let properties = device.physical_device().properties();
611 
612         // VUID-vkCmdBeginRendering-dynamicRendering-06446
613         if !device.enabled_features().dynamic_rendering {
614             return Err(RenderPassError::RequirementNotMet {
615                 required_for: "`AutoCommandBufferBuilder::begin_rendering`",
616                 requires_one_of: RequiresOneOf {
617                     features: &["dynamic_rendering"],
618                     ..Default::default()
619                 },
620             });
621         }
622 
623         let queue_family_properties = self.queue_family_properties();
624 
625         // VUID-vkCmdBeginRendering-commandBuffer-cmdpool
626         if !queue_family_properties
627             .queue_flags
628             .intersects(QueueFlags::GRAPHICS)
629         {
630             return Err(RenderPassError::NotSupportedByQueueFamily);
631         }
632 
633         // VUID-vkCmdBeginRendering-renderpass
634         if self.render_pass_state.is_some() {
635             return Err(RenderPassError::ForbiddenInsideRenderPass);
636         }
637 
638         let &mut RenderingInfo {
639             render_area_offset,
640             render_area_extent,
641             layer_count,
642             view_mask,
643             ref color_attachments,
644             ref depth_attachment,
645             ref stencil_attachment,
646             contents,
647             _ne: _,
648         } = rendering_info;
649 
650         // VUID-VkRenderingInfo-flags-parameter
651         contents.validate_device(device)?;
652 
653         // VUID-vkCmdBeginRendering-commandBuffer-06068
654         if self.inheritance_info.is_some() && contents == SubpassContents::SecondaryCommandBuffers {
655             return Err(RenderPassError::ContentsForbiddenInSecondaryCommandBuffer);
656         }
657 
658         // No VUID, but for sanity it makes sense to treat this the same as in framebuffers.
659         if view_mask != 0 && layer_count != 1 {
660             return Err(RenderPassError::MultiviewLayersInvalid);
661         }
662 
663         // VUID-VkRenderingInfo-multiview-06127
664         if view_mask != 0 && !device.enabled_features().multiview {
665             return Err(RenderPassError::RequirementNotMet {
666                 required_for: "`rendering_info.viewmask` is not `0`",
667                 requires_one_of: RequiresOneOf {
668                     features: &["multiview"],
669                     ..Default::default()
670                 },
671             });
672         }
673 
674         let view_count = u32::BITS - view_mask.leading_zeros();
675 
676         // VUID-VkRenderingInfo-viewMask-06128
677         if view_count > properties.max_multiview_view_count.unwrap_or(0) {
678             return Err(RenderPassError::MaxMultiviewViewCountExceeded {
679                 view_count,
680                 max: properties.max_multiview_view_count.unwrap_or(0),
681             });
682         }
683 
684         let mut samples = None;
685 
686         // VUID-VkRenderingInfo-colorAttachmentCount-06106
687         if color_attachments.len() > properties.max_color_attachments as usize {
688             return Err(RenderPassError::MaxColorAttachmentsExceeded {
689                 color_attachment_count: color_attachments.len() as u32,
690                 max: properties.max_color_attachments,
691             });
692         }
693 
694         for (attachment_index, attachment_info) in
695             color_attachments
696                 .iter()
697                 .enumerate()
698                 .filter_map(|(index, attachment_info)| {
699                     attachment_info
700                         .as_ref()
701                         .map(|attachment_info| (index, attachment_info))
702                 })
703         {
704             let attachment_index = attachment_index as u32;
705             let RenderingAttachmentInfo {
706                 image_view,
707                 image_layout,
708                 resolve_info,
709                 load_op,
710                 store_op,
711                 clear_value: _,
712                 _ne: _,
713             } = attachment_info;
714 
715             // VUID-VkRenderingAttachmentInfo-imageLayout-parameter
716             image_layout.validate_device(device)?;
717 
718             // VUID-VkRenderingAttachmentInfo-loadOp-parameter
719             load_op.validate_device(device)?;
720 
721             // VUID-VkRenderingAttachmentInfo-storeOp-parameter
722             store_op.validate_device(device)?;
723 
724             // VUID-VkRenderingInfo-colorAttachmentCount-06087
725             if !image_view.usage().intersects(ImageUsage::COLOR_ATTACHMENT) {
726                 return Err(RenderPassError::ColorAttachmentMissingUsage { attachment_index });
727             }
728 
729             let image = image_view.image();
730             let image_extent = image.dimensions().width_height_depth();
731 
732             for i in 0..2 {
733                 // VUID-VkRenderingInfo-pNext-06079
734                 // VUID-VkRenderingInfo-pNext-06080
735                 if render_area_offset[i] + render_area_extent[i] > image_extent[i] {
736                     return Err(RenderPassError::RenderAreaOutOfBounds);
737                 }
738             }
739 
740             // VUID-VkRenderingInfo-imageView-06070
741             match samples {
742                 Some(samples) if samples == image.samples() => (),
743                 Some(_) => {
744                     return Err(RenderPassError::ColorAttachmentSamplesMismatch {
745                         attachment_index,
746                     });
747                 }
748                 None => samples = Some(image.samples()),
749             }
750 
751             // VUID-VkRenderingAttachmentInfo-imageView-06135
752             // VUID-VkRenderingAttachmentInfo-imageView-06145
753             // VUID-VkRenderingInfo-colorAttachmentCount-06090
754             // VUID-VkRenderingInfo-colorAttachmentCount-06096
755             if matches!(
756                 image_layout,
757                 ImageLayout::Undefined
758                     | ImageLayout::ShaderReadOnlyOptimal
759                     | ImageLayout::TransferSrcOptimal
760                     | ImageLayout::TransferDstOptimal
761                     | ImageLayout::Preinitialized
762                     | ImageLayout::PresentSrc
763                     | ImageLayout::DepthStencilAttachmentOptimal
764                     | ImageLayout::DepthStencilReadOnlyOptimal
765                     | ImageLayout::DepthReadOnlyStencilAttachmentOptimal
766                     | ImageLayout::DepthAttachmentStencilReadOnlyOptimal
767             ) {
768                 return Err(RenderPassError::ColorAttachmentLayoutInvalid { attachment_index });
769             }
770 
771             if let Some(resolve_info) = resolve_info {
772                 let &RenderingAttachmentResolveInfo {
773                     mode,
774                     image_view: ref resolve_image_view,
775                     image_layout: resolve_image_layout,
776                 } = resolve_info;
777 
778                 // VUID-VkRenderingAttachmentInfo-resolveImageLayout-parameter
779                 resolve_image_layout.validate_device(device)?;
780 
781                 // VUID-VkRenderingAttachmentInfo-resolveMode-parameter
782                 mode.validate_device(device)?;
783 
784                 let resolve_image = resolve_image_view.image();
785 
786                 match image_view.format().unwrap().type_color() {
787                     Some(
788                         NumericType::SFLOAT
789                         | NumericType::UFLOAT
790                         | NumericType::SNORM
791                         | NumericType::UNORM
792                         | NumericType::SSCALED
793                         | NumericType::USCALED
794                         | NumericType::SRGB,
795                     ) => {
796                         // VUID-VkRenderingAttachmentInfo-imageView-06129
797                         if mode != ResolveMode::Average {
798                             return Err(RenderPassError::ColorAttachmentResolveModeNotSupported {
799                                 attachment_index,
800                             });
801                         }
802                     }
803                     Some(NumericType::SINT | NumericType::UINT) => {
804                         // VUID-VkRenderingAttachmentInfo-imageView-06130
805                         if mode != ResolveMode::SampleZero {
806                             return Err(RenderPassError::ColorAttachmentResolveModeNotSupported {
807                                 attachment_index,
808                             });
809                         }
810                     }
811                     None => (),
812                 }
813 
814                 // VUID-VkRenderingAttachmentInfo-imageView-06132
815                 if image.samples() == SampleCount::Sample1 {
816                     return Err(RenderPassError::ColorAttachmentWithResolveNotMultisampled {
817                         attachment_index,
818                     });
819                 }
820 
821                 // VUID-VkRenderingAttachmentInfo-imageView-06133
822                 if resolve_image.samples() != SampleCount::Sample1 {
823                     return Err(RenderPassError::ColorAttachmentResolveMultisampled {
824                         attachment_index,
825                     });
826                 }
827 
828                 // VUID-VkRenderingAttachmentInfo-imageView-06134
829                 if image_view.format() != resolve_image_view.format() {
830                     return Err(RenderPassError::ColorAttachmentResolveFormatMismatch {
831                         attachment_index,
832                     });
833                 }
834 
835                 // VUID-VkRenderingAttachmentInfo-imageView-06136
836                 // VUID-VkRenderingAttachmentInfo-imageView-06146
837                 // VUID-VkRenderingInfo-colorAttachmentCount-06091
838                 // VUID-VkRenderingInfo-colorAttachmentCount-06097
839                 if matches!(
840                     resolve_image_layout,
841                     ImageLayout::Undefined
842                         | ImageLayout::ShaderReadOnlyOptimal
843                         | ImageLayout::TransferSrcOptimal
844                         | ImageLayout::TransferDstOptimal
845                         | ImageLayout::Preinitialized
846                         | ImageLayout::PresentSrc
847                         | ImageLayout::DepthStencilAttachmentOptimal
848                         | ImageLayout::DepthStencilReadOnlyOptimal
849                         | ImageLayout::DepthReadOnlyStencilAttachmentOptimal
850                         | ImageLayout::DepthAttachmentStencilReadOnlyOptimal
851                 ) {
852                     return Err(RenderPassError::ColorAttachmentResolveLayoutInvalid {
853                         attachment_index,
854                     });
855                 }
856             }
857         }
858 
859         if let Some(attachment_info) = depth_attachment {
860             let RenderingAttachmentInfo {
861                 image_view,
862                 image_layout,
863                 resolve_info,
864                 load_op,
865                 store_op,
866                 clear_value: _,
867                 _ne: _,
868             } = attachment_info;
869 
870             // VUID-VkRenderingAttachmentInfo-imageLayout-parameter
871             image_layout.validate_device(device)?;
872 
873             // VUID-VkRenderingAttachmentInfo-loadOp-parameter
874             load_op.validate_device(device)?;
875 
876             // VUID-VkRenderingAttachmentInfo-storeOp-parameter
877             store_op.validate_device(device)?;
878 
879             let image_aspects = image_view.format().unwrap().aspects();
880 
881             // VUID-VkRenderingInfo-pDepthAttachment-06547
882             if !image_aspects.intersects(ImageAspects::DEPTH) {
883                 return Err(RenderPassError::DepthAttachmentFormatUsageNotSupported);
884             }
885 
886             // VUID-VkRenderingInfo-pDepthAttachment-06088
887             if !image_view
888                 .usage()
889                 .intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
890             {
891                 return Err(RenderPassError::DepthAttachmentMissingUsage);
892             }
893 
894             let image = image_view.image();
895             let image_extent = image.dimensions().width_height_depth();
896 
897             for i in 0..2 {
898                 // VUID-VkRenderingInfo-pNext-06079
899                 // VUID-VkRenderingInfo-pNext-06080
900                 if render_area_offset[i] + render_area_extent[i] > image_extent[i] {
901                     return Err(RenderPassError::RenderAreaOutOfBounds);
902                 }
903             }
904 
905             // VUID-VkRenderingInfo-imageView-06070
906             match samples {
907                 Some(samples) if samples == image.samples() => (),
908                 Some(_) => {
909                     return Err(RenderPassError::DepthAttachmentSamplesMismatch);
910                 }
911                 None => samples = Some(image.samples()),
912             }
913 
914             // VUID-VkRenderingAttachmentInfo-imageView-06135
915             // VUID-VkRenderingAttachmentInfo-imageView-06145
916             // VUID-VkRenderingInfo-pDepthAttachment-06092
917             if matches!(
918                 image_layout,
919                 ImageLayout::Undefined
920                     | ImageLayout::ShaderReadOnlyOptimal
921                     | ImageLayout::TransferSrcOptimal
922                     | ImageLayout::TransferDstOptimal
923                     | ImageLayout::Preinitialized
924                     | ImageLayout::PresentSrc
925                     | ImageLayout::ColorAttachmentOptimal
926             ) {
927                 return Err(RenderPassError::DepthAttachmentLayoutInvalid);
928             }
929 
930             if let Some(resolve_info) = resolve_info {
931                 let &RenderingAttachmentResolveInfo {
932                     mode,
933                     image_view: ref resolve_image_view,
934                     image_layout: resolve_image_layout,
935                 } = resolve_info;
936 
937                 // VUID-VkRenderingAttachmentInfo-resolveImageLayout-parameter
938                 resolve_image_layout.validate_device(device)?;
939 
940                 // VUID-VkRenderingAttachmentInfo-resolveMode-parameter
941                 mode.validate_device(device)?;
942 
943                 // VUID-VkRenderingInfo-pDepthAttachment-06102
944                 if !properties
945                     .supported_depth_resolve_modes
946                     .map_or(false, |modes| modes.contains_enum(mode))
947                 {
948                     return Err(RenderPassError::DepthAttachmentResolveModeNotSupported);
949                 }
950 
951                 let resolve_image = resolve_image_view.image();
952 
953                 // VUID-VkRenderingAttachmentInfo-imageView-06132
954                 if image.samples() == SampleCount::Sample1 {
955                     return Err(RenderPassError::DepthAttachmentWithResolveNotMultisampled);
956                 }
957 
958                 // VUID-VkRenderingAttachmentInfo-imageView-06133
959                 if resolve_image.samples() != SampleCount::Sample1 {
960                     return Err(RenderPassError::DepthAttachmentResolveMultisampled);
961                 }
962 
963                 // VUID-VkRenderingAttachmentInfo-imageView-06134
964                 if image_view.format() != resolve_image_view.format() {
965                     return Err(RenderPassError::DepthAttachmentResolveFormatMismatch);
966                 }
967 
968                 // VUID-VkRenderingAttachmentInfo-imageView-06136
969                 // VUID-VkRenderingAttachmentInfo-imageView-06146
970                 // VUID-VkRenderingInfo-pDepthAttachment-06093
971                 // VUID-VkRenderingInfo-pDepthAttachment-06098
972                 if matches!(
973                     resolve_image_layout,
974                     ImageLayout::Undefined
975                         | ImageLayout::DepthStencilReadOnlyOptimal
976                         | ImageLayout::ShaderReadOnlyOptimal
977                         | ImageLayout::TransferSrcOptimal
978                         | ImageLayout::TransferDstOptimal
979                         | ImageLayout::Preinitialized
980                         | ImageLayout::PresentSrc
981                         | ImageLayout::ColorAttachmentOptimal
982                         | ImageLayout::DepthReadOnlyStencilAttachmentOptimal
983                 ) {
984                     return Err(RenderPassError::DepthAttachmentResolveLayoutInvalid);
985                 }
986             }
987         }
988 
989         if let Some(attachment_info) = stencil_attachment {
990             let RenderingAttachmentInfo {
991                 image_view,
992                 image_layout,
993                 resolve_info,
994                 load_op,
995                 store_op,
996                 clear_value: _,
997                 _ne: _,
998             } = attachment_info;
999 
1000             // VUID-VkRenderingAttachmentInfo-imageLayout-parameter
1001             image_layout.validate_device(device)?;
1002 
1003             // VUID-VkRenderingAttachmentInfo-loadOp-parameter
1004             load_op.validate_device(device)?;
1005 
1006             // VUID-VkRenderingAttachmentInfo-storeOp-parameter
1007             store_op.validate_device(device)?;
1008 
1009             let image_aspects = image_view.format().unwrap().aspects();
1010 
1011             // VUID-VkRenderingInfo-pStencilAttachment-06548
1012             if !image_aspects.intersects(ImageAspects::STENCIL) {
1013                 return Err(RenderPassError::StencilAttachmentFormatUsageNotSupported);
1014             }
1015 
1016             // VUID-VkRenderingInfo-pStencilAttachment-06089
1017             if !image_view
1018                 .usage()
1019                 .intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
1020             {
1021                 return Err(RenderPassError::StencilAttachmentMissingUsage);
1022             }
1023 
1024             let image = image_view.image();
1025             let image_extent = image.dimensions().width_height_depth();
1026 
1027             for i in 0..2 {
1028                 // VUID-VkRenderingInfo-pNext-06079
1029                 // VUID-VkRenderingInfo-pNext-06080
1030                 if render_area_offset[i] + render_area_extent[i] > image_extent[i] {
1031                     return Err(RenderPassError::RenderAreaOutOfBounds);
1032                 }
1033             }
1034 
1035             // VUID-VkRenderingInfo-imageView-06070
1036             match samples {
1037                 Some(samples) if samples == image.samples() => (),
1038                 Some(_) => {
1039                     return Err(RenderPassError::StencilAttachmentSamplesMismatch);
1040                 }
1041                 None => (),
1042             }
1043 
1044             // VUID-VkRenderingAttachmentInfo-imageView-06135
1045             // VUID-VkRenderingAttachmentInfo-imageView-06145
1046             // VUID-VkRenderingInfo-pStencilAttachment-06094
1047             if matches!(
1048                 image_layout,
1049                 ImageLayout::Undefined
1050                     | ImageLayout::ShaderReadOnlyOptimal
1051                     | ImageLayout::TransferSrcOptimal
1052                     | ImageLayout::TransferDstOptimal
1053                     | ImageLayout::Preinitialized
1054                     | ImageLayout::PresentSrc
1055                     | ImageLayout::ColorAttachmentOptimal
1056             ) {
1057                 return Err(RenderPassError::StencilAttachmentLayoutInvalid);
1058             }
1059 
1060             if let Some(resolve_info) = resolve_info {
1061                 let &RenderingAttachmentResolveInfo {
1062                     mode,
1063                     image_view: ref resolve_image_view,
1064                     image_layout: resolve_image_layout,
1065                 } = resolve_info;
1066 
1067                 // VUID-VkRenderingAttachmentInfo-resolveImageLayout-parameter
1068                 resolve_image_layout.validate_device(device)?;
1069 
1070                 // VUID-VkRenderingAttachmentInfo-resolveMode-parameter
1071                 mode.validate_device(device)?;
1072 
1073                 // VUID-VkRenderingInfo-pStencilAttachment-06103
1074                 if !properties
1075                     .supported_stencil_resolve_modes
1076                     .map_or(false, |modes| modes.contains_enum(mode))
1077                 {
1078                     return Err(RenderPassError::StencilAttachmentResolveModeNotSupported);
1079                 }
1080 
1081                 let resolve_image = resolve_image_view.image();
1082 
1083                 // VUID-VkRenderingAttachmentInfo-imageView-06132
1084                 if image.samples() == SampleCount::Sample1 {
1085                     return Err(RenderPassError::StencilAttachmentWithResolveNotMultisampled);
1086                 }
1087 
1088                 // VUID-VkRenderingAttachmentInfo-imageView-06133
1089                 if resolve_image.samples() != SampleCount::Sample1 {
1090                     return Err(RenderPassError::StencilAttachmentResolveMultisampled);
1091                 }
1092 
1093                 // VUID-VkRenderingAttachmentInfo-imageView-06134
1094                 if image_view.format() != resolve_image_view.format() {
1095                     return Err(RenderPassError::StencilAttachmentResolveFormatMismatch);
1096                 }
1097 
1098                 // VUID-VkRenderingAttachmentInfo-imageView-06136
1099                 // VUID-VkRenderingAttachmentInfo-imageView-06146
1100                 // VUID-VkRenderingInfo-pStencilAttachment-06095
1101                 // VUID-VkRenderingInfo-pStencilAttachment-06099
1102                 if matches!(
1103                     resolve_image_layout,
1104                     ImageLayout::Undefined
1105                         | ImageLayout::DepthStencilReadOnlyOptimal
1106                         | ImageLayout::ShaderReadOnlyOptimal
1107                         | ImageLayout::TransferSrcOptimal
1108                         | ImageLayout::TransferDstOptimal
1109                         | ImageLayout::Preinitialized
1110                         | ImageLayout::PresentSrc
1111                         | ImageLayout::ColorAttachmentOptimal
1112                         | ImageLayout::DepthAttachmentStencilReadOnlyOptimal
1113                 ) {
1114                     return Err(RenderPassError::StencilAttachmentResolveLayoutInvalid);
1115                 }
1116             }
1117         }
1118 
1119         if let (Some(depth_attachment_info), Some(stencil_attachment_info)) =
1120             (depth_attachment, stencil_attachment)
1121         {
1122             // VUID-VkRenderingInfo-pDepthAttachment-06085
1123             if &depth_attachment_info.image_view != &stencil_attachment_info.image_view {
1124                 return Err(RenderPassError::DepthStencilAttachmentImageViewMismatch);
1125             }
1126 
1127             match (
1128                 &depth_attachment_info.resolve_info,
1129                 &stencil_attachment_info.resolve_info,
1130             ) {
1131                 (None, None) => (),
1132                 (None, Some(_)) | (Some(_), None) => {
1133                     // VUID-VkRenderingInfo-pDepthAttachment-06104
1134                     if !properties.independent_resolve_none.unwrap_or(false) {
1135                         return Err(
1136                             RenderPassError::DepthStencilAttachmentResolveModesNotSupported,
1137                         );
1138                     }
1139                 }
1140                 (Some(depth_resolve_info), Some(stencil_resolve_info)) => {
1141                     // VUID-VkRenderingInfo-pDepthAttachment-06105
1142                     if !properties.independent_resolve.unwrap_or(false)
1143                         && depth_resolve_info.mode != stencil_resolve_info.mode
1144                     {
1145                         return Err(
1146                             RenderPassError::DepthStencilAttachmentResolveModesNotSupported,
1147                         );
1148                     }
1149 
1150                     // VUID-VkRenderingInfo-pDepthAttachment-06086
1151                     if &depth_resolve_info.image_view != &stencil_resolve_info.image_view {
1152                         return Err(
1153                             RenderPassError::DepthStencilAttachmentResolveImageViewMismatch,
1154                         );
1155                     }
1156                 }
1157             }
1158         }
1159 
1160         Ok(())
1161     }
1162 
1163     /// Ends the render pass previously begun with `begin_rendering`.
end_rendering(&mut self) -> Result<&mut Self, RenderPassError>1164     pub fn end_rendering(&mut self) -> Result<&mut Self, RenderPassError> {
1165         self.validate_end_rendering()?;
1166 
1167         unsafe {
1168             self.inner.end_rendering();
1169             self.render_pass_state = None;
1170         }
1171 
1172         Ok(self)
1173     }
1174 
validate_end_rendering(&self) -> Result<(), RenderPassError>1175     fn validate_end_rendering(&self) -> Result<(), RenderPassError> {
1176         // VUID-vkCmdEndRendering-renderpass
1177         let render_pass_state = self
1178             .render_pass_state
1179             .as_ref()
1180             .ok_or(RenderPassError::ForbiddenOutsideRenderPass)?;
1181 
1182         // VUID?
1183         if self.inheritance_info.is_some() {
1184             return Err(RenderPassError::ForbiddenWithInheritedRenderPass);
1185         }
1186 
1187         // VUID-vkCmdEndRendering-None-06161
1188         // VUID-vkCmdEndRendering-commandBuffer-06162
1189         match &render_pass_state.render_pass {
1190             RenderPassStateType::BeginRenderPass(_) => {
1191                 return Err(RenderPassError::ForbiddenWithBeginRenderPass)
1192             }
1193             RenderPassStateType::BeginRendering(_) => (),
1194         }
1195 
1196         // VUID-vkCmdEndRendering-commandBuffer-cmdpool
1197         debug_assert!(self
1198             .queue_family_properties()
1199             .queue_flags
1200             .intersects(QueueFlags::GRAPHICS));
1201 
1202         Ok(())
1203     }
1204 
1205     /// Clears specific regions of specific attachments of the framebuffer.
1206     ///
1207     /// `attachments` specify the types of attachments and their clear values.
1208     /// `rects` specify the regions to clear.
1209     ///
1210     /// A graphics pipeline must have been bound using
1211     /// [`bind_pipeline_graphics`](Self::bind_pipeline_graphics). And the command must be inside render pass.
1212     ///
1213     /// If the render pass instance this is recorded in uses multiview,
1214     /// then `ClearRect.base_array_layer` must be zero and `ClearRect.layer_count` must be one.
1215     ///
1216     /// The rectangle area must be inside the render area ranges.
clear_attachments( &mut self, attachments: impl IntoIterator<Item = ClearAttachment>, rects: impl IntoIterator<Item = ClearRect>, ) -> Result<&mut Self, RenderPassError>1217     pub fn clear_attachments(
1218         &mut self,
1219         attachments: impl IntoIterator<Item = ClearAttachment>,
1220         rects: impl IntoIterator<Item = ClearRect>,
1221     ) -> Result<&mut Self, RenderPassError> {
1222         let attachments: SmallVec<[ClearAttachment; 3]> = attachments.into_iter().collect();
1223         let rects: SmallVec<[ClearRect; 4]> = rects.into_iter().collect();
1224 
1225         self.validate_clear_attachments(&attachments, &rects)?;
1226 
1227         unsafe {
1228             self.inner.clear_attachments(attachments, rects);
1229         }
1230 
1231         Ok(self)
1232     }
1233 
validate_clear_attachments( &self, attachments: &[ClearAttachment], rects: &[ClearRect], ) -> Result<(), RenderPassError>1234     fn validate_clear_attachments(
1235         &self,
1236         attachments: &[ClearAttachment],
1237         rects: &[ClearRect],
1238     ) -> Result<(), RenderPassError> {
1239         // VUID-vkCmdClearAttachments-renderpass
1240         let render_pass_state = self
1241             .render_pass_state
1242             .as_ref()
1243             .ok_or(RenderPassError::ForbiddenOutsideRenderPass)?;
1244 
1245         if render_pass_state.contents != SubpassContents::Inline {
1246             return Err(RenderPassError::ForbiddenWithSubpassContents {
1247                 contents: render_pass_state.contents,
1248             });
1249         }
1250 
1251         //let subpass_desc = begin_render_pass_state.subpass.subpass_desc();
1252         //let render_pass = begin_render_pass_state.subpass.render_pass();
1253         let is_multiview = render_pass_state.view_mask != 0;
1254         let mut layer_count = u32::MAX;
1255 
1256         for &clear_attachment in attachments {
1257             match clear_attachment {
1258                 ClearAttachment::Color {
1259                     color_attachment,
1260                     clear_value,
1261                 } => {
1262                     let attachment_format = match &render_pass_state.render_pass {
1263                         RenderPassStateType::BeginRenderPass(state) => {
1264                             let color_attachments = &state.subpass.subpass_desc().color_attachments;
1265                             let atch_ref = color_attachments.get(color_attachment as usize).ok_or(
1266                                 RenderPassError::ColorAttachmentIndexOutOfRange {
1267                                     color_attachment_index: color_attachment,
1268                                     num_color_attachments: color_attachments.len() as u32,
1269                                 },
1270                             )?;
1271 
1272                             atch_ref.as_ref().map(|atch_ref| {
1273                                 state.subpass.render_pass().attachments()
1274                                     [atch_ref.attachment as usize]
1275                                     .format
1276                                     .unwrap()
1277                             })
1278                         }
1279                         RenderPassStateType::BeginRendering(state) => *state
1280                             .color_attachment_formats
1281                             .get(color_attachment as usize)
1282                             .ok_or(RenderPassError::ColorAttachmentIndexOutOfRange {
1283                                 color_attachment_index: color_attachment,
1284                                 num_color_attachments: state.color_attachment_formats.len() as u32,
1285                             })?,
1286                     };
1287 
1288                     // VUID-vkCmdClearAttachments-aspectMask-02501
1289                     if !attachment_format.map_or(false, |format| {
1290                         matches!(
1291                             (clear_value, format.type_color().unwrap()),
1292                             (
1293                                 ClearColorValue::Float(_),
1294                                 NumericType::SFLOAT
1295                                     | NumericType::UFLOAT
1296                                     | NumericType::SNORM
1297                                     | NumericType::UNORM
1298                                     | NumericType::SSCALED
1299                                     | NumericType::USCALED
1300                                     | NumericType::SRGB
1301                             ) | (ClearColorValue::Int(_), NumericType::SINT)
1302                                 | (ClearColorValue::Uint(_), NumericType::UINT)
1303                         )
1304                     }) {
1305                         return Err(RenderPassError::ClearAttachmentNotCompatible {
1306                             clear_attachment,
1307                             attachment_format,
1308                         });
1309                     }
1310 
1311                     let image_view = match &render_pass_state.render_pass {
1312                         RenderPassStateType::BeginRenderPass(state) => (state.framebuffer.as_ref())
1313                             .zip(
1314                                 state.subpass.subpass_desc().color_attachments
1315                                     [color_attachment as usize]
1316                                     .as_ref(),
1317                             )
1318                             .map(|(framebuffer, atch_ref)| {
1319                                 &framebuffer.attachments()[atch_ref.attachment as usize]
1320                             }),
1321                         RenderPassStateType::BeginRendering(state) => state
1322                             .attachments
1323                             .as_ref()
1324                             .and_then(|attachments| {
1325                                 attachments.color_attachments[color_attachment as usize].as_ref()
1326                             })
1327                             .map(|attachment_info| &attachment_info.image_view),
1328                     };
1329 
1330                     // We only know the layer count if we have a known attachment image.
1331                     if let Some(image_view) = image_view {
1332                         let array_layers = &image_view.subresource_range().array_layers;
1333                         layer_count = min(layer_count, array_layers.end - array_layers.start);
1334                     }
1335                 }
1336                 ClearAttachment::Depth(_)
1337                 | ClearAttachment::Stencil(_)
1338                 | ClearAttachment::DepthStencil(_) => {
1339                     let (depth_format, stencil_format) = match &render_pass_state.render_pass {
1340                         RenderPassStateType::BeginRenderPass(state) => state
1341                             .subpass
1342                             .subpass_desc()
1343                             .depth_stencil_attachment
1344                             .as_ref()
1345                             .map_or((None, None), |atch_ref| {
1346                                 let format = state.subpass.render_pass().attachments()
1347                                     [atch_ref.attachment as usize]
1348                                     .format
1349                                     .unwrap();
1350                                 (Some(format), Some(format))
1351                             }),
1352                         RenderPassStateType::BeginRendering(state) => (
1353                             state.depth_attachment_format,
1354                             state.stencil_attachment_format,
1355                         ),
1356                     };
1357 
1358                     // VUID-vkCmdClearAttachments-aspectMask-02502
1359                     if matches!(
1360                         clear_attachment,
1361                         ClearAttachment::Depth(_) | ClearAttachment::DepthStencil(_)
1362                     ) && !depth_format.map_or(false, |format| {
1363                         format.aspects().intersects(ImageAspects::DEPTH)
1364                     }) {
1365                         return Err(RenderPassError::ClearAttachmentNotCompatible {
1366                             clear_attachment,
1367                             attachment_format: None,
1368                         });
1369                     }
1370 
1371                     // VUID-vkCmdClearAttachments-aspectMask-02503
1372                     if matches!(
1373                         clear_attachment,
1374                         ClearAttachment::Stencil(_) | ClearAttachment::DepthStencil(_)
1375                     ) && !stencil_format.map_or(false, |format| {
1376                         format.aspects().intersects(ImageAspects::STENCIL)
1377                     }) {
1378                         return Err(RenderPassError::ClearAttachmentNotCompatible {
1379                             clear_attachment,
1380                             attachment_format: None,
1381                         });
1382                     }
1383 
1384                     let image_view = match &render_pass_state.render_pass {
1385                         RenderPassStateType::BeginRenderPass(state) => (state.framebuffer.as_ref())
1386                             .zip(
1387                                 state
1388                                     .subpass
1389                                     .subpass_desc()
1390                                     .depth_stencil_attachment
1391                                     .as_ref(),
1392                             )
1393                             .map(|(framebuffer, atch_ref)| {
1394                                 &framebuffer.attachments()[atch_ref.attachment as usize]
1395                             }),
1396                         RenderPassStateType::BeginRendering(state) => state
1397                             .attachments
1398                             .as_ref()
1399                             .and_then(|attachments| attachments.depth_attachment.as_ref())
1400                             .map(|attachment_info| &attachment_info.image_view),
1401                     };
1402 
1403                     // We only know the layer count if we have a known attachment image.
1404                     if let Some(image_view) = image_view {
1405                         let array_layers = &image_view.subresource_range().array_layers;
1406                         layer_count = min(layer_count, array_layers.end - array_layers.start);
1407                     }
1408                 }
1409             }
1410         }
1411 
1412         for (rect_index, rect) in rects.iter().enumerate() {
1413             for i in 0..2 {
1414                 // VUID-vkCmdClearAttachments-rect-02682
1415                 // VUID-vkCmdClearAttachments-rect-02683
1416                 if rect.extent[i] == 0 {
1417                     return Err(RenderPassError::RectExtentZero { rect_index });
1418                 }
1419 
1420                 // VUID-vkCmdClearAttachments-pRects-00016
1421                 // TODO: This check will always pass in secondary command buffers because of how
1422                 // it's set in `with_level`.
1423                 // It needs to be checked during `execute_commands` instead.
1424                 if rect.offset[i] < render_pass_state.render_area_offset[i]
1425                     || rect.offset[i] + rect.extent[i]
1426                         > render_pass_state.render_area_offset[i]
1427                             + render_pass_state.render_area_extent[i]
1428                 {
1429                     return Err(RenderPassError::RectOutOfBounds { rect_index });
1430                 }
1431             }
1432 
1433             // VUID-vkCmdClearAttachments-layerCount-01934
1434             if rect.array_layers.is_empty() {
1435                 return Err(RenderPassError::RectArrayLayersEmpty { rect_index });
1436             }
1437 
1438             // VUID-vkCmdClearAttachments-pRects-00017
1439             if rect.array_layers.end > layer_count {
1440                 return Err(RenderPassError::RectArrayLayersOutOfBounds { rect_index });
1441             }
1442 
1443             // VUID-vkCmdClearAttachments-baseArrayLayer-00018
1444             if is_multiview && rect.array_layers != (0..1) {
1445                 return Err(RenderPassError::MultiviewRectArrayLayersInvalid { rect_index });
1446             }
1447         }
1448 
1449         // VUID-vkCmdClearAttachments-commandBuffer-cmdpool
1450         debug_assert!(self
1451             .queue_family_properties()
1452             .queue_flags
1453             .intersects(QueueFlags::GRAPHICS));
1454 
1455         Ok(())
1456     }
1457 }
1458 
1459 impl SyncCommandBufferBuilder {
1460     /// Calls `vkCmdBeginRenderPass` on the builder.
1461     // TODO: it shouldn't be possible to get an error if the framebuffer checked conflicts already
1462     // TODO: after begin_render_pass has been called, flushing should be forbidden and an error
1463     //       returned if conflict
1464     #[inline]
begin_render_pass( &mut self, render_pass_begin_info: RenderPassBeginInfo, contents: SubpassContents, ) -> Result<(), SyncCommandBufferBuilderError>1465     pub unsafe fn begin_render_pass(
1466         &mut self,
1467         render_pass_begin_info: RenderPassBeginInfo,
1468         contents: SubpassContents,
1469     ) -> Result<(), SyncCommandBufferBuilderError> {
1470         struct Cmd {
1471             render_pass_begin_info: RenderPassBeginInfo,
1472             contents: SubpassContents,
1473         }
1474 
1475         impl Command for Cmd {
1476             fn name(&self) -> &'static str {
1477                 "begin_render_pass"
1478             }
1479 
1480             unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) {
1481                 out.begin_render_pass(&self.render_pass_begin_info, self.contents);
1482             }
1483         }
1484 
1485         let RenderPassBeginInfo {
1486             render_pass,
1487             framebuffer,
1488             render_area_offset: _,
1489             render_area_extent: _,
1490             clear_values: _,
1491             _ne: _,
1492         } = &render_pass_begin_info;
1493 
1494         let command_index = self.commands.len();
1495         let command_name = "begin_render_pass";
1496         let resources = render_pass
1497             .attachments()
1498             .iter()
1499             .enumerate()
1500             .map(|(index, desc)| {
1501                 let image_view = &framebuffer.attachments()[index];
1502                 let index = index as u32;
1503 
1504                 (
1505                     ResourceUseRef {
1506                         command_index,
1507                         command_name,
1508                         resource_in_command: ResourceInCommand::FramebufferAttachment { index },
1509                         secondary_use_ref: None,
1510                     },
1511                     Resource::Image {
1512                         image: image_view.image(),
1513                         subresource_range: image_view.subresource_range().clone(),
1514                         memory: PipelineMemoryAccess {
1515                             stages: PipelineStages::ALL_COMMANDS, // TODO: wrong!
1516                             access: AccessFlags::INPUT_ATTACHMENT_READ
1517                                 | AccessFlags::COLOR_ATTACHMENT_READ
1518                                 | AccessFlags::COLOR_ATTACHMENT_WRITE
1519                                 | AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ
1520                                 | AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE, // TODO: suboptimal
1521                             exclusive: true, // TODO: suboptimal ; note: remember to always pass true if desc.initial_layout != desc.final_layout
1522                         },
1523                         start_layout: desc.initial_layout,
1524                         end_layout: desc.final_layout,
1525                     },
1526                 )
1527             })
1528             .collect::<Vec<_>>();
1529 
1530         for resource in &resources {
1531             self.check_resource_conflicts(resource)?;
1532         }
1533 
1534         self.commands.push(Box::new(Cmd {
1535             render_pass_begin_info,
1536             contents,
1537         }));
1538 
1539         for resource in resources {
1540             self.add_resource(resource);
1541         }
1542 
1543         self.latest_render_pass_enter = Some(self.commands.len() - 1);
1544 
1545         Ok(())
1546     }
1547 
1548     /// Calls `vkCmdNextSubpass` on the builder.
1549     #[inline]
next_subpass(&mut self, contents: SubpassContents)1550     pub unsafe fn next_subpass(&mut self, contents: SubpassContents) {
1551         struct Cmd {
1552             contents: SubpassContents,
1553         }
1554 
1555         impl Command for Cmd {
1556             fn name(&self) -> &'static str {
1557                 "next_subpass"
1558             }
1559 
1560             unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) {
1561                 out.next_subpass(self.contents);
1562             }
1563         }
1564 
1565         self.commands.push(Box::new(Cmd { contents }));
1566     }
1567 
1568     /// Calls `vkCmdEndRenderPass` on the builder.
1569     #[inline]
end_render_pass(&mut self)1570     pub unsafe fn end_render_pass(&mut self) {
1571         struct Cmd;
1572 
1573         impl Command for Cmd {
1574             fn name(&self) -> &'static str {
1575                 "end_render_pass"
1576             }
1577 
1578             unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) {
1579                 out.end_render_pass();
1580             }
1581         }
1582 
1583         self.commands.push(Box::new(Cmd));
1584         debug_assert!(self.latest_render_pass_enter.is_some());
1585         self.latest_render_pass_enter = None;
1586     }
1587 
1588     /// Calls `vkCmdBeginRendering` on the builder.
1589     #[inline]
begin_rendering( &mut self, rendering_info: RenderingInfo, ) -> Result<(), SyncCommandBufferBuilderError>1590     pub unsafe fn begin_rendering(
1591         &mut self,
1592         rendering_info: RenderingInfo,
1593     ) -> Result<(), SyncCommandBufferBuilderError> {
1594         struct Cmd {
1595             rendering_info: RenderingInfo,
1596         }
1597 
1598         impl Command for Cmd {
1599             fn name(&self) -> &'static str {
1600                 "begin_rendering"
1601             }
1602 
1603             unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) {
1604                 out.begin_rendering(&self.rendering_info);
1605             }
1606         }
1607 
1608         let RenderingInfo {
1609             render_area_offset: _,
1610             render_area_extent: _,
1611             layer_count: _,
1612             view_mask: _,
1613             color_attachments,
1614             depth_attachment,
1615             stencil_attachment,
1616             contents: _,
1617             _ne,
1618         } = &rendering_info;
1619 
1620         let command_index = self.commands.len();
1621         let command_name = "begin_rendering";
1622         let resources = (color_attachments
1623             .iter()
1624             .enumerate()
1625             .filter_map(|(index, attachment_info)| {
1626                 attachment_info
1627                     .as_ref()
1628                     .map(|attachment_info| (index as u32, attachment_info))
1629             })
1630             .flat_map(|(index, attachment_info)| {
1631                 let &RenderingAttachmentInfo {
1632                     ref image_view,
1633                     image_layout,
1634                     ref resolve_info,
1635                     load_op: _,
1636                     store_op: _,
1637                     clear_value: _,
1638                     _ne: _,
1639                 } = attachment_info;
1640 
1641                 [
1642                     Some((
1643                         ResourceUseRef {
1644                             command_index,
1645                             command_name,
1646                             resource_in_command: ResourceInCommand::ColorAttachment { index },
1647                             secondary_use_ref: None,
1648                         },
1649                         Resource::Image {
1650                             image: image_view.image(),
1651                             subresource_range: image_view.subresource_range().clone(),
1652                             memory: PipelineMemoryAccess {
1653                                 stages: PipelineStages::ALL_COMMANDS, // TODO: wrong!
1654                                 access: AccessFlags::COLOR_ATTACHMENT_READ
1655                                     | AccessFlags::COLOR_ATTACHMENT_WRITE, // TODO: suboptimal
1656                                 exclusive: true,                      // TODO: suboptimal
1657                             },
1658                             start_layout: image_layout,
1659                             end_layout: image_layout,
1660                         },
1661                     )),
1662                     resolve_info.as_ref().map(|resolve_info| {
1663                         let &RenderingAttachmentResolveInfo {
1664                             mode: _,
1665                             ref image_view,
1666                             image_layout,
1667                         } = resolve_info;
1668 
1669                         (
1670                             ResourceUseRef {
1671                                 command_index,
1672                                 command_name,
1673                                 resource_in_command: ResourceInCommand::ColorResolveAttachment {
1674                                     index,
1675                                 },
1676                                 secondary_use_ref: None,
1677                             },
1678                             Resource::Image {
1679                                 image: image_view.image(),
1680                                 subresource_range: image_view.subresource_range().clone(),
1681                                 memory: PipelineMemoryAccess {
1682                                     stages: PipelineStages::ALL_COMMANDS, // TODO: wrong!
1683                                     access: AccessFlags::COLOR_ATTACHMENT_READ
1684                                         | AccessFlags::COLOR_ATTACHMENT_WRITE, // TODO: suboptimal
1685                                     exclusive: true,                      // TODO: suboptimal
1686                                 },
1687                                 start_layout: image_layout,
1688                                 end_layout: image_layout,
1689                             },
1690                         )
1691                     }),
1692                 ]
1693                 .into_iter()
1694                 .flatten()
1695             }))
1696         .chain(depth_attachment.iter().flat_map(|attachment_info| {
1697             let &RenderingAttachmentInfo {
1698                 ref image_view,
1699                 image_layout,
1700                 ref resolve_info,
1701                 load_op: _,
1702                 store_op: _,
1703                 clear_value: _,
1704                 _ne: _,
1705             } = attachment_info;
1706 
1707             [
1708                 Some((
1709                     ResourceUseRef {
1710                         command_index,
1711                         command_name,
1712                         resource_in_command: ResourceInCommand::DepthStencilAttachment,
1713                         secondary_use_ref: None,
1714                     },
1715                     Resource::Image {
1716                         image: image_view.image(),
1717                         subresource_range: image_view.subresource_range().clone(),
1718                         memory: PipelineMemoryAccess {
1719                             stages: PipelineStages::ALL_COMMANDS, // TODO: wrong!
1720                             access: AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ
1721                                 | AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE, // TODO: suboptimal
1722                             exclusive: true,                      // TODO: suboptimal
1723                         },
1724                         start_layout: image_layout,
1725                         end_layout: image_layout,
1726                     },
1727                 )),
1728                 resolve_info.as_ref().map(|resolve_info| {
1729                     let &RenderingAttachmentResolveInfo {
1730                         mode: _,
1731                         ref image_view,
1732                         image_layout,
1733                     } = resolve_info;
1734 
1735                     (
1736                         ResourceUseRef {
1737                             command_index,
1738                             command_name,
1739                             resource_in_command: ResourceInCommand::DepthStencilResolveAttachment,
1740                             secondary_use_ref: None,
1741                         },
1742                         Resource::Image {
1743                             image: image_view.image(),
1744                             subresource_range: image_view.subresource_range().clone(),
1745                             memory: PipelineMemoryAccess {
1746                                 stages: PipelineStages::ALL_COMMANDS, // TODO: wrong!
1747                                 access: AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ
1748                                     | AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE, // TODO: suboptimal
1749                                 exclusive: true, // TODO: suboptimal
1750                             },
1751                             start_layout: image_layout,
1752                             end_layout: image_layout,
1753                         },
1754                     )
1755                 }),
1756             ]
1757             .into_iter()
1758             .flatten()
1759         }))
1760         .chain(stencil_attachment.iter().flat_map(|attachment_info| {
1761             let &RenderingAttachmentInfo {
1762                 ref image_view,
1763                 image_layout,
1764                 ref resolve_info,
1765                 load_op: _,
1766                 store_op: _,
1767                 clear_value: _,
1768                 _ne: _,
1769             } = attachment_info;
1770 
1771             [
1772                 Some((
1773                     ResourceUseRef {
1774                         command_index,
1775                         command_name,
1776                         resource_in_command: ResourceInCommand::DepthStencilAttachment,
1777                         secondary_use_ref: None,
1778                     },
1779                     Resource::Image {
1780                         image: image_view.image(),
1781                         subresource_range: image_view.subresource_range().clone(),
1782                         memory: PipelineMemoryAccess {
1783                             stages: PipelineStages::ALL_COMMANDS, // TODO: wrong!
1784                             access: AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ
1785                                 | AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE, // TODO: suboptimal
1786                             exclusive: true,                      // TODO: suboptimal
1787                         },
1788                         start_layout: image_layout,
1789                         end_layout: image_layout,
1790                     },
1791                 )),
1792                 resolve_info.as_ref().map(|resolve_info| {
1793                     let &RenderingAttachmentResolveInfo {
1794                         mode: _,
1795                         ref image_view,
1796                         image_layout,
1797                     } = resolve_info;
1798 
1799                     (
1800                         ResourceUseRef {
1801                             command_index,
1802                             command_name,
1803                             resource_in_command: ResourceInCommand::DepthStencilResolveAttachment,
1804                             secondary_use_ref: None,
1805                         },
1806                         Resource::Image {
1807                             image: image_view.image(),
1808                             subresource_range: image_view.subresource_range().clone(),
1809                             memory: PipelineMemoryAccess {
1810                                 stages: PipelineStages::ALL_COMMANDS, // TODO: wrong!
1811                                 access: AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ
1812                                     | AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE, // TODO: suboptimal
1813                                 exclusive: true, // TODO: suboptimal
1814                             },
1815                             start_layout: image_layout,
1816                             end_layout: image_layout,
1817                         },
1818                     )
1819                 }),
1820             ]
1821             .into_iter()
1822             .flatten()
1823         }))
1824         .collect::<Vec<_>>();
1825 
1826         for resource in &resources {
1827             self.check_resource_conflicts(resource)?;
1828         }
1829 
1830         self.commands.push(Box::new(Cmd { rendering_info }));
1831 
1832         for resource in resources {
1833             self.add_resource(resource);
1834         }
1835 
1836         self.latest_render_pass_enter = Some(self.commands.len() - 1);
1837 
1838         Ok(())
1839     }
1840 
1841     /// Calls `vkCmdEndRendering` on the builder.
1842     #[inline]
end_rendering(&mut self)1843     pub unsafe fn end_rendering(&mut self) {
1844         struct Cmd;
1845 
1846         impl Command for Cmd {
1847             fn name(&self) -> &'static str {
1848                 "end_rendering"
1849             }
1850 
1851             unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) {
1852                 out.end_rendering();
1853             }
1854         }
1855 
1856         self.commands.push(Box::new(Cmd));
1857         debug_assert!(self.latest_render_pass_enter.is_some());
1858         self.latest_render_pass_enter = None;
1859     }
1860 
1861     /// Calls `vkCmdClearAttachments` on the builder.
1862     ///
1863     /// Does nothing if the list of attachments or the list of rects is empty, as it would be a
1864     /// no-op and isn't a valid usage of the command anyway.
clear_attachments( &mut self, attachments: impl IntoIterator<Item = ClearAttachment>, rects: impl IntoIterator<Item = ClearRect>, )1865     pub unsafe fn clear_attachments(
1866         &mut self,
1867         attachments: impl IntoIterator<Item = ClearAttachment>,
1868         rects: impl IntoIterator<Item = ClearRect>,
1869     ) {
1870         struct Cmd {
1871             attachments: SmallVec<[ClearAttachment; 3]>,
1872             rects: SmallVec<[ClearRect; 4]>,
1873         }
1874 
1875         impl Command for Cmd {
1876             fn name(&self) -> &'static str {
1877                 "clear_attachments"
1878             }
1879 
1880             unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) {
1881                 out.clear_attachments(self.attachments.iter().copied(), self.rects.iter().cloned());
1882             }
1883         }
1884         let attachments: SmallVec<[_; 3]> = attachments.into_iter().collect();
1885         let rects: SmallVec<[_; 4]> = rects.into_iter().collect();
1886 
1887         self.commands.push(Box::new(Cmd { attachments, rects }));
1888     }
1889 }
1890 
1891 impl UnsafeCommandBufferBuilder {
1892     /// Calls `vkCmdBeginRenderPass` on the builder.
1893     #[inline]
begin_render_pass( &mut self, render_pass_begin_info: &RenderPassBeginInfo, contents: SubpassContents, )1894     pub unsafe fn begin_render_pass(
1895         &mut self,
1896         render_pass_begin_info: &RenderPassBeginInfo,
1897         contents: SubpassContents,
1898     ) {
1899         let &RenderPassBeginInfo {
1900             ref render_pass,
1901             ref framebuffer,
1902             render_area_offset,
1903             render_area_extent,
1904             ref clear_values,
1905             _ne: _,
1906         } = render_pass_begin_info;
1907 
1908         let clear_values_vk: SmallVec<[_; 4]> = clear_values
1909             .iter()
1910             .copied()
1911             .map(|clear_value| clear_value.map(Into::into).unwrap_or_default())
1912             .collect();
1913 
1914         let render_pass_begin_info = ash::vk::RenderPassBeginInfo {
1915             render_pass: render_pass.handle(),
1916             framebuffer: framebuffer.handle(),
1917             render_area: ash::vk::Rect2D {
1918                 offset: ash::vk::Offset2D {
1919                     x: render_area_offset[0] as i32,
1920                     y: render_area_offset[1] as i32,
1921                 },
1922                 extent: ash::vk::Extent2D {
1923                     width: render_area_extent[0],
1924                     height: render_area_extent[1],
1925                 },
1926             },
1927             clear_value_count: clear_values_vk.len() as u32,
1928             p_clear_values: clear_values_vk.as_ptr(),
1929             ..Default::default()
1930         };
1931 
1932         let subpass_begin_info = ash::vk::SubpassBeginInfo {
1933             contents: contents.into(),
1934             ..Default::default()
1935         };
1936 
1937         let fns = self.device.fns();
1938 
1939         if self.device.api_version() >= Version::V1_2
1940             || self.device.enabled_extensions().khr_create_renderpass2
1941         {
1942             if self.device.api_version() >= Version::V1_2 {
1943                 (fns.v1_2.cmd_begin_render_pass2)(
1944                     self.handle,
1945                     &render_pass_begin_info,
1946                     &subpass_begin_info,
1947                 );
1948             } else {
1949                 (fns.khr_create_renderpass2.cmd_begin_render_pass2_khr)(
1950                     self.handle,
1951                     &render_pass_begin_info,
1952                     &subpass_begin_info,
1953                 );
1954             }
1955         } else {
1956             debug_assert!(subpass_begin_info.p_next.is_null());
1957 
1958             (fns.v1_0.cmd_begin_render_pass)(
1959                 self.handle,
1960                 &render_pass_begin_info,
1961                 subpass_begin_info.contents,
1962             );
1963         }
1964     }
1965 
1966     /// Calls `vkCmdNextSubpass` on the builder.
1967     #[inline]
next_subpass(&mut self, contents: SubpassContents)1968     pub unsafe fn next_subpass(&mut self, contents: SubpassContents) {
1969         let fns = self.device.fns();
1970 
1971         let subpass_begin_info = ash::vk::SubpassBeginInfo {
1972             contents: contents.into(),
1973             ..Default::default()
1974         };
1975 
1976         let subpass_end_info = ash::vk::SubpassEndInfo::default();
1977 
1978         if self.device.api_version() >= Version::V1_2
1979             || self.device.enabled_extensions().khr_create_renderpass2
1980         {
1981             if self.device.api_version() >= Version::V1_2 {
1982                 (fns.v1_2.cmd_next_subpass2)(self.handle, &subpass_begin_info, &subpass_end_info);
1983             } else {
1984                 (fns.khr_create_renderpass2.cmd_next_subpass2_khr)(
1985                     self.handle,
1986                     &subpass_begin_info,
1987                     &subpass_end_info,
1988                 );
1989             }
1990         } else {
1991             debug_assert!(subpass_begin_info.p_next.is_null());
1992             debug_assert!(subpass_end_info.p_next.is_null());
1993 
1994             (fns.v1_0.cmd_next_subpass)(self.handle, subpass_begin_info.contents);
1995         }
1996     }
1997 
1998     /// Calls `vkCmdEndRenderPass` on the builder.
1999     #[inline]
end_render_pass(&mut self)2000     pub unsafe fn end_render_pass(&mut self) {
2001         let fns = self.device.fns();
2002 
2003         let subpass_end_info = ash::vk::SubpassEndInfo::default();
2004 
2005         if self.device.api_version() >= Version::V1_2
2006             || self.device.enabled_extensions().khr_create_renderpass2
2007         {
2008             if self.device.api_version() >= Version::V1_2 {
2009                 (fns.v1_2.cmd_end_render_pass2)(self.handle, &subpass_end_info);
2010             } else {
2011                 (fns.khr_create_renderpass2.cmd_end_render_pass2_khr)(
2012                     self.handle,
2013                     &subpass_end_info,
2014                 );
2015             }
2016         } else {
2017             debug_assert!(subpass_end_info.p_next.is_null());
2018 
2019             (fns.v1_0.cmd_end_render_pass)(self.handle);
2020         }
2021     }
2022 
2023     /// Calls `vkCmdBeginRendering` on the builder.
2024     #[inline]
begin_rendering(&mut self, rendering_info: &RenderingInfo)2025     pub unsafe fn begin_rendering(&mut self, rendering_info: &RenderingInfo) {
2026         let &RenderingInfo {
2027             render_area_offset,
2028             render_area_extent,
2029             layer_count,
2030             view_mask,
2031             ref color_attachments,
2032             ref depth_attachment,
2033             ref stencil_attachment,
2034             contents,
2035             _ne: _,
2036         } = rendering_info;
2037 
2038         let map_attachment_info = |attachment_info: &Option<_>| {
2039             if let Some(attachment_info) = attachment_info {
2040                 let &RenderingAttachmentInfo {
2041                     ref image_view,
2042                     image_layout,
2043                     resolve_info: ref resolve,
2044                     load_op,
2045                     store_op,
2046                     clear_value,
2047                     _ne: _,
2048                 } = attachment_info;
2049 
2050                 let (resolve_mode, resolve_image_view, resolve_image_layout) =
2051                     if let Some(resolve) = resolve {
2052                         let &RenderingAttachmentResolveInfo {
2053                             mode,
2054                             ref image_view,
2055                             image_layout,
2056                         } = resolve;
2057 
2058                         (mode.into(), image_view.handle(), image_layout.into())
2059                     } else {
2060                         (
2061                             ash::vk::ResolveModeFlags::NONE,
2062                             Default::default(),
2063                             Default::default(),
2064                         )
2065                     };
2066 
2067                 ash::vk::RenderingAttachmentInfo {
2068                     image_view: image_view.handle(),
2069                     image_layout: image_layout.into(),
2070                     resolve_mode,
2071                     resolve_image_view,
2072                     resolve_image_layout,
2073                     load_op: load_op.into(),
2074                     store_op: store_op.into(),
2075                     clear_value: clear_value.map_or_else(Default::default, Into::into),
2076                     ..Default::default()
2077                 }
2078             } else {
2079                 ash::vk::RenderingAttachmentInfo {
2080                     image_view: ash::vk::ImageView::null(),
2081                     ..Default::default()
2082                 }
2083             }
2084         };
2085 
2086         let color_attachments: SmallVec<[_; 2]> =
2087             color_attachments.iter().map(map_attachment_info).collect();
2088         let depth_attachment = map_attachment_info(depth_attachment);
2089         let stencil_attachment = map_attachment_info(stencil_attachment);
2090 
2091         let rendering_info = ash::vk::RenderingInfo {
2092             flags: contents.into(),
2093             render_area: ash::vk::Rect2D {
2094                 offset: ash::vk::Offset2D {
2095                     x: render_area_offset[0] as i32,
2096                     y: render_area_offset[1] as i32,
2097                 },
2098                 extent: ash::vk::Extent2D {
2099                     width: render_area_extent[0],
2100                     height: render_area_extent[1],
2101                 },
2102             },
2103             layer_count,
2104             view_mask,
2105             color_attachment_count: color_attachments.len() as u32,
2106             p_color_attachments: color_attachments.as_ptr(),
2107             p_depth_attachment: &depth_attachment,
2108             p_stencil_attachment: &stencil_attachment,
2109             ..Default::default()
2110         };
2111 
2112         let fns = self.device.fns();
2113 
2114         if self.device.api_version() >= Version::V1_3 {
2115             (fns.v1_3.cmd_begin_rendering)(self.handle, &rendering_info);
2116         } else {
2117             debug_assert!(self.device.enabled_extensions().khr_dynamic_rendering);
2118             (fns.khr_dynamic_rendering.cmd_begin_rendering_khr)(self.handle, &rendering_info);
2119         }
2120     }
2121 
2122     /// Calls `vkCmdEndRendering` on the builder.
2123     #[inline]
end_rendering(&mut self)2124     pub unsafe fn end_rendering(&mut self) {
2125         let fns = self.device.fns();
2126 
2127         if self.device.api_version() >= Version::V1_3 {
2128             (fns.v1_3.cmd_end_rendering)(self.handle);
2129         } else {
2130             debug_assert!(self.device.enabled_extensions().khr_dynamic_rendering);
2131             (fns.khr_dynamic_rendering.cmd_end_rendering_khr)(self.handle);
2132         }
2133     }
2134 
2135     /// Calls `vkCmdClearAttachments` on the builder.
2136     ///
2137     /// Does nothing if the list of attachments or the list of rects is empty, as it would be a
2138     /// no-op and isn't a valid usage of the command anyway.
clear_attachments( &mut self, attachments: impl IntoIterator<Item = ClearAttachment>, rects: impl IntoIterator<Item = ClearRect>, )2139     pub unsafe fn clear_attachments(
2140         &mut self,
2141         attachments: impl IntoIterator<Item = ClearAttachment>,
2142         rects: impl IntoIterator<Item = ClearRect>,
2143     ) {
2144         let attachments: SmallVec<[_; 3]> = attachments.into_iter().map(|v| v.into()).collect();
2145         let rects: SmallVec<[_; 4]> = rects
2146             .into_iter()
2147             .map(|rect| ash::vk::ClearRect {
2148                 rect: ash::vk::Rect2D {
2149                     offset: ash::vk::Offset2D {
2150                         x: rect.offset[0] as i32,
2151                         y: rect.offset[1] as i32,
2152                     },
2153                     extent: ash::vk::Extent2D {
2154                         width: rect.extent[0],
2155                         height: rect.extent[1],
2156                     },
2157                 },
2158                 base_array_layer: rect.array_layers.start,
2159                 layer_count: rect.array_layers.end - rect.array_layers.start,
2160             })
2161             .collect();
2162 
2163         if attachments.is_empty() || rects.is_empty() {
2164             return;
2165         }
2166 
2167         let fns = self.device.fns();
2168         (fns.v1_0.cmd_clear_attachments)(
2169             self.handle,
2170             attachments.len() as u32,
2171             attachments.as_ptr(),
2172             rects.len() as u32,
2173             rects.as_ptr(),
2174         );
2175     }
2176 }
2177 
2178 /// Parameters to begin a new render pass.
2179 #[derive(Clone, Debug)]
2180 pub struct RenderPassBeginInfo {
2181     /// The render pass to begin.
2182     ///
2183     /// If this is not the render pass that `framebuffer` was created with, it must be compatible
2184     /// with that render pass.
2185     ///
2186     /// The default value is the render pass of `framebuffer`.
2187     pub render_pass: Arc<RenderPass>,
2188 
2189     /// The framebuffer to use for rendering.
2190     ///
2191     /// There is no default value.
2192     pub framebuffer: Arc<Framebuffer>,
2193 
2194     /// The offset from the top left corner of the framebuffer that will be rendered to.
2195     ///
2196     /// The default value is `[0, 0]`.
2197     pub render_area_offset: [u32; 2],
2198 
2199     /// The size of the area that will be rendered to.
2200     ///
2201     /// `render_area_offset + render_area_extent` must not be greater than [`framebuffer.extent()`].
2202     ///
2203     /// The default value is [`framebuffer.extent()`].
2204     pub render_area_extent: [u32; 2],
2205 
2206     /// Provides, for each attachment in `render_pass` that has a load operation of
2207     /// [`LoadOp::Clear`], the clear values that should be used for the attachments in the
2208     /// framebuffer. There must be exactly [`framebuffer.attachments().len()`] elements provided,
2209     /// and each one must match the attachment format.
2210     ///
2211     /// To skip over an attachment whose load operation is something else, provide `None`.
2212     ///
2213     /// The default value is empty, which must be overridden if the framebuffer has attachments.
2214     pub clear_values: Vec<Option<ClearValue>>,
2215 
2216     pub _ne: crate::NonExhaustive,
2217 }
2218 
2219 impl RenderPassBeginInfo {
2220     #[inline]
framebuffer(framebuffer: Arc<Framebuffer>) -> Self2221     pub fn framebuffer(framebuffer: Arc<Framebuffer>) -> Self {
2222         let render_area_extent = framebuffer.extent();
2223 
2224         Self {
2225             render_pass: framebuffer.render_pass().clone(),
2226             framebuffer,
2227             render_area_offset: [0, 0],
2228             render_area_extent,
2229             clear_values: Vec::new(),
2230             _ne: crate::NonExhaustive(()),
2231         }
2232     }
2233 }
2234 
2235 /// Parameters to begin rendering.
2236 #[derive(Clone, Debug)]
2237 pub struct RenderingInfo {
2238     /// The offset from the top left corner of the attachments that will be rendered to.
2239     ///
2240     /// This value must be smaller than the smallest width and height of the attachment images.
2241     ///
2242     /// The default value is `[0, 0]`.
2243     pub render_area_offset: [u32; 2],
2244 
2245     /// The size of the area that will be rendered to.
2246     ///
2247     /// This value plus `render_area_offset` must be no larger than the smallest width and height
2248     /// of the attachment images.
2249     /// If one of the elements is set to 0, the extent will be calculated automatically from the
2250     /// extents of the attachment images to be the largest allowed. At least one attachment image
2251     /// must be specified in that case.
2252     ///
2253     /// The default value is `[0, 0]`.
2254     pub render_area_extent: [u32; 2],
2255 
2256     /// The number of layers of the attachments that will be rendered to.
2257     ///
2258     /// This must be no larger than the smallest number of array layers of the attachment images.
2259     /// If set to 0, the number of layers will be calculated automatically from the
2260     /// layer ranges of the attachment images to be the largest allowed. At least one attachment
2261     /// image must be specified in that case.
2262     ///
2263     /// If the render pass uses multiview (`view_mask` is not 0), then this value must be 0 or 1.
2264     ///
2265     /// The default value is `0`.
2266     pub layer_count: u32,
2267 
2268     /// If not `0`, enables multiview rendering, and specifies the view indices that are rendered
2269     /// to. The value is a bitmask, so that that for example `0b11` will draw to the first two
2270     /// views and `0b101` will draw to the first and third view.
2271     ///
2272     /// If set to a nonzero value, the [`multiview`](crate::device::Features::multiview) feature
2273     /// must be enabled on the device.
2274     ///
2275     /// The default value is `0`.
2276     pub view_mask: u32,
2277 
2278     /// The color attachments to use for rendering.
2279     ///
2280     /// The number of color attachments must be less than the
2281     /// [`max_color_attachments`](crate::device::Properties::max_color_attachments) limit of the
2282     /// physical device. All color attachments must have the same `samples` value.
2283     ///
2284     /// The default value is empty.
2285     pub color_attachments: Vec<Option<RenderingAttachmentInfo>>,
2286 
2287     /// The depth attachment to use for rendering.
2288     ///
2289     /// If set to `Some`, the image view must have the same `samples` value as those in
2290     /// `color_attachments`.
2291     ///
2292     /// The default value is `None`.
2293     pub depth_attachment: Option<RenderingAttachmentInfo>,
2294 
2295     /// The stencil attachment to use for rendering.
2296     ///
2297     /// If set to `Some`, the image view must have the same `samples` value as those in
2298     /// `color_attachments`.
2299     ///
2300     /// The default value is `None`.
2301     pub stencil_attachment: Option<RenderingAttachmentInfo>,
2302 
2303     /// What kinds of commands will be recorded in the render pass: either inline draw commands, or
2304     /// executions of secondary command buffers.
2305     ///
2306     /// If recorded in a secondary command buffer, this must be [`SubpassContents::Inline`].
2307     ///
2308     /// The default value is [`SubpassContents::Inline`].
2309     pub contents: SubpassContents,
2310 
2311     pub _ne: crate::NonExhaustive,
2312 }
2313 
2314 impl Default for RenderingInfo {
2315     #[inline]
default() -> Self2316     fn default() -> Self {
2317         Self {
2318             render_area_offset: [0, 0],
2319             render_area_extent: [0, 0],
2320             layer_count: 0,
2321             view_mask: 0,
2322             color_attachments: Vec::new(),
2323             depth_attachment: None,
2324             stencil_attachment: None,
2325             contents: SubpassContents::Inline,
2326             _ne: crate::NonExhaustive(()),
2327         }
2328     }
2329 }
2330 
2331 impl RenderingInfo {
set_extent_layers(&mut self) -> Result<(), RenderPassError>2332     pub(crate) fn set_extent_layers(&mut self) -> Result<(), RenderPassError> {
2333         let &mut RenderingInfo {
2334             render_area_offset,
2335             ref mut render_area_extent,
2336             ref mut layer_count,
2337             view_mask,
2338             ref color_attachments,
2339             ref depth_attachment,
2340             ref stencil_attachment,
2341             contents: _,
2342             _ne: _,
2343         } = self;
2344 
2345         let auto_extent = render_area_extent[0] == 0 || render_area_extent[1] == 0;
2346         let auto_layers = *layer_count == 0;
2347 
2348         // Set the values based on the attachment sizes.
2349         if auto_extent || auto_layers {
2350             if auto_extent {
2351                 *render_area_extent = [u32::MAX, u32::MAX];
2352             }
2353 
2354             if auto_layers {
2355                 if view_mask != 0 {
2356                     *layer_count = 1;
2357                 } else {
2358                     *layer_count = u32::MAX;
2359                 }
2360             }
2361 
2362             for image_view in (color_attachments.iter().flatten())
2363                 .chain(depth_attachment.iter())
2364                 .chain(stencil_attachment.iter())
2365                 .flat_map(|attachment_info| {
2366                     Some(&attachment_info.image_view).into_iter().chain(
2367                         attachment_info
2368                             .resolve_info
2369                             .as_ref()
2370                             .map(|resolve_info| &resolve_info.image_view),
2371                     )
2372                 })
2373             {
2374                 if auto_extent {
2375                     let extent = image_view.dimensions().width_height();
2376 
2377                     for i in 0..2 {
2378                         render_area_extent[i] = min(render_area_extent[i], extent[i]);
2379                     }
2380                 }
2381 
2382                 if auto_layers {
2383                     let subresource_range = image_view.subresource_range();
2384                     let array_layers =
2385                         subresource_range.array_layers.end - subresource_range.array_layers.start;
2386 
2387                     *layer_count = min(*layer_count, array_layers);
2388                 }
2389             }
2390 
2391             if auto_extent {
2392                 if *render_area_extent == [u32::MAX, u32::MAX] {
2393                     return Err(RenderPassError::AutoExtentAttachmentsEmpty);
2394                 }
2395 
2396                 // Subtract the offset from the calculated max extent.
2397                 // If there is an underflow, then the offset is too large, and validation should
2398                 // catch that later.
2399                 for i in 0..2 {
2400                     render_area_extent[i] = render_area_extent[i]
2401                         .checked_sub(render_area_offset[i])
2402                         .unwrap_or(1);
2403                 }
2404             }
2405 
2406             if auto_layers {
2407                 if *layer_count == u32::MAX {
2408                     return Err(RenderPassError::AutoLayersAttachmentsEmpty);
2409                 }
2410             }
2411         }
2412 
2413         Ok(())
2414     }
2415 }
2416 
2417 /// Parameters to specify properties of an attachment.
2418 #[derive(Clone, Debug)]
2419 pub struct RenderingAttachmentInfo {
2420     /// The image view to use as the attachment.
2421     ///
2422     /// There is no default value.
2423     pub image_view: Arc<dyn ImageViewAbstract>,
2424 
2425     /// The image layout that `image_view` should be in during the resolve operation.
2426     ///
2427     /// The default value is [`ImageLayout::ColorAttachmentOptimal`] if `image_view` has a color
2428     /// format, [`ImageLayout::DepthStencilAttachmentOptimal`] if `image_view` has a depth/stencil
2429     /// format.
2430     pub image_layout: ImageLayout,
2431 
2432     /// The resolve operation that should be performed at the end of rendering.
2433     ///
2434     /// The default value is `None`.
2435     pub resolve_info: Option<RenderingAttachmentResolveInfo>,
2436 
2437     /// What the implementation should do with the attachment at the start of rendering.
2438     ///
2439     /// The default value is [`LoadOp::DontCare`].
2440     pub load_op: LoadOp,
2441 
2442     /// What the implementation should do with the attachment at the end of rendering.
2443     ///
2444     /// The default value is [`StoreOp::DontCare`].
2445     pub store_op: StoreOp,
2446 
2447     /// If `load_op` is [`LoadOp::Clear`], specifies the clear value that should be used for the
2448     /// attachment.
2449     ///
2450     /// If `load_op` is something else, provide `None`.
2451     ///
2452     /// The default value is `None`.
2453     pub clear_value: Option<ClearValue>,
2454 
2455     pub _ne: crate::NonExhaustive,
2456 }
2457 
2458 impl RenderingAttachmentInfo {
2459     /// Returns a `RenderingAttachmentInfo` with the specified `image_view`.
2460     #[inline]
image_view(image_view: Arc<dyn ImageViewAbstract>) -> Self2461     pub fn image_view(image_view: Arc<dyn ImageViewAbstract>) -> Self {
2462         let aspects = image_view.format().unwrap().aspects();
2463         let image_layout = if aspects.intersects(ImageAspects::DEPTH | ImageAspects::STENCIL) {
2464             ImageLayout::DepthStencilAttachmentOptimal
2465         } else {
2466             ImageLayout::ColorAttachmentOptimal
2467         };
2468 
2469         Self {
2470             image_view,
2471             image_layout,
2472             resolve_info: None,
2473             load_op: LoadOp::DontCare,
2474             store_op: StoreOp::DontCare,
2475             clear_value: None,
2476             _ne: crate::NonExhaustive(()),
2477         }
2478     }
2479 }
2480 
2481 /// Parameters to specify the resolve behavior of an attachment.
2482 #[derive(Clone, Debug)]
2483 pub struct RenderingAttachmentResolveInfo {
2484     /// How the resolve operation should be performed.
2485     ///
2486     /// The default value is [`ResolveMode::Average`].
2487     pub mode: ResolveMode,
2488 
2489     /// The image view that the result of the resolve operation should be written to.
2490     ///
2491     /// There is no default value.
2492     pub image_view: Arc<dyn ImageViewAbstract>,
2493 
2494     /// The image layout that `image_view` should be in during the resolve operation.
2495     ///
2496     /// The default value is [`ImageLayout::ColorAttachmentOptimal`] if `image_view` has a color
2497     /// format, [`ImageLayout::DepthStencilAttachmentOptimal`] if `image_view` has a depth/stencil
2498     /// format.
2499     pub image_layout: ImageLayout,
2500 }
2501 
2502 impl RenderingAttachmentResolveInfo {
2503     /// Returns a `RenderingAttachmentResolveInfo` with the specified `image_view`.
2504     #[inline]
image_view(image_view: Arc<dyn ImageViewAbstract>) -> Self2505     pub fn image_view(image_view: Arc<dyn ImageViewAbstract>) -> Self {
2506         let aspects = image_view.format().unwrap().aspects();
2507         let image_layout = if aspects.intersects(ImageAspects::DEPTH | ImageAspects::STENCIL) {
2508             ImageLayout::DepthStencilAttachmentOptimal
2509         } else {
2510             ImageLayout::ColorAttachmentOptimal
2511         };
2512 
2513         Self {
2514             mode: ResolveMode::Average,
2515             image_view,
2516             image_layout,
2517         }
2518     }
2519 }
2520 
2521 /// Clear attachment type, used in [`clear_attachments`] command.
2522 ///
2523 /// [`clear_attachments`]: crate::command_buffer::AutoCommandBufferBuilder::clear_attachments
2524 #[derive(Clone, Copy, Debug)]
2525 pub enum ClearAttachment {
2526     /// Clear the color attachment at the specified index, with the specified clear value.
2527     Color {
2528         color_attachment: u32,
2529         clear_value: ClearColorValue,
2530     },
2531 
2532     /// Clear the depth attachment with the specified depth value.
2533     Depth(f32),
2534 
2535     /// Clear the stencil attachment with the specified stencil value.
2536     Stencil(u32),
2537 
2538     /// Clear the depth and stencil attachments with the specified depth and stencil values.
2539     DepthStencil((f32, u32)),
2540 }
2541 
2542 impl From<ClearAttachment> for ash::vk::ClearAttachment {
2543     #[inline]
from(v: ClearAttachment) -> Self2544     fn from(v: ClearAttachment) -> Self {
2545         match v {
2546             ClearAttachment::Color {
2547                 color_attachment,
2548                 clear_value,
2549             } => ash::vk::ClearAttachment {
2550                 aspect_mask: ash::vk::ImageAspectFlags::COLOR,
2551                 color_attachment,
2552                 clear_value: ash::vk::ClearValue {
2553                     color: clear_value.into(),
2554                 },
2555             },
2556             ClearAttachment::Depth(depth) => ash::vk::ClearAttachment {
2557                 aspect_mask: ash::vk::ImageAspectFlags::DEPTH,
2558                 color_attachment: 0,
2559                 clear_value: ash::vk::ClearValue {
2560                     depth_stencil: ash::vk::ClearDepthStencilValue { depth, stencil: 0 },
2561                 },
2562             },
2563             ClearAttachment::Stencil(stencil) => ash::vk::ClearAttachment {
2564                 aspect_mask: ash::vk::ImageAspectFlags::STENCIL,
2565                 color_attachment: 0,
2566                 clear_value: ash::vk::ClearValue {
2567                     depth_stencil: ash::vk::ClearDepthStencilValue {
2568                         depth: 0.0,
2569                         stencil,
2570                     },
2571                 },
2572             },
2573             ClearAttachment::DepthStencil((depth, stencil)) => ash::vk::ClearAttachment {
2574                 aspect_mask: ash::vk::ImageAspectFlags::DEPTH | ash::vk::ImageAspectFlags::STENCIL,
2575                 color_attachment: 0,
2576                 clear_value: ash::vk::ClearValue {
2577                     depth_stencil: ash::vk::ClearDepthStencilValue { depth, stencil },
2578                 },
2579             },
2580         }
2581     }
2582 }
2583 
2584 /// Specifies the clear region for the [`clear_attachments`] command.
2585 ///
2586 /// [`clear_attachments`]: crate::command_buffer::AutoCommandBufferBuilder::clear_attachments
2587 #[derive(Clone, Debug, PartialEq, Eq)]
2588 pub struct ClearRect {
2589     /// The rectangle offset.
2590     pub offset: [u32; 2],
2591 
2592     /// The width and height of the rectangle.
2593     pub extent: [u32; 2],
2594 
2595     /// The range of array layers to be cleared.
2596     pub array_layers: Range<u32>,
2597 }
2598 
2599 /// Error that can happen when recording a render pass command.
2600 #[derive(Clone, Debug)]
2601 pub enum RenderPassError {
2602     SyncCommandBufferBuilderError(SyncCommandBufferBuilderError),
2603 
2604     RequirementNotMet {
2605         required_for: &'static str,
2606         requires_one_of: RequiresOneOf,
2607     },
2608 
2609     /// A framebuffer image did not have the required usage enabled.
2610     AttachmentImageMissingUsage {
2611         attachment_index: u32,
2612         usage: &'static str,
2613     },
2614 
2615     /// One of the elements of `render_pass_extent` is zero, but no attachment images were given to
2616     /// calculate the extent from.
2617     AutoExtentAttachmentsEmpty,
2618 
2619     /// `layer_count` is zero, but no attachment images were given to calculate the number of layers
2620     /// from.
2621     AutoLayersAttachmentsEmpty,
2622 
2623     /// A clear attachment value is not compatible with the attachment's format.
2624     ClearAttachmentNotCompatible {
2625         clear_attachment: ClearAttachment,
2626         attachment_format: Option<Format>,
2627     },
2628 
2629     /// A clear value for a render pass attachment is missing.
2630     ClearValueMissing {
2631         attachment_index: u32,
2632     },
2633 
2634     /// A clear value provided for a render pass attachment is not compatible with the attachment's
2635     /// format.
2636     ClearValueNotCompatible {
2637         clear_value: ClearValue,
2638         attachment_index: u32,
2639         attachment_format: Format,
2640     },
2641 
2642     /// An attachment clear value specifies a `color_attachment` index that is not less than the
2643     /// number of color attachments in the subpass.
2644     ColorAttachmentIndexOutOfRange {
2645         color_attachment_index: u32,
2646         num_color_attachments: u32,
2647     },
2648 
2649     /// A color attachment has a layout that is not supported.
2650     ColorAttachmentLayoutInvalid {
2651         attachment_index: u32,
2652     },
2653 
2654     /// A color attachment is missing the `color_attachment` usage.
2655     ColorAttachmentMissingUsage {
2656         attachment_index: u32,
2657     },
2658 
2659     /// A color resolve attachment has a `format` value different from the corresponding color
2660     /// attachment.
2661     ColorAttachmentResolveFormatMismatch {
2662         attachment_index: u32,
2663     },
2664 
2665     /// A color resolve attachment has a layout that is not supported.
2666     ColorAttachmentResolveLayoutInvalid {
2667         attachment_index: u32,
2668     },
2669 
2670     /// A color resolve attachment has a resolve mode that is not supported.
2671     ColorAttachmentResolveModeNotSupported {
2672         attachment_index: u32,
2673     },
2674 
2675     /// A color resolve attachment has a `samples` value other than [`SampleCount::Sample1`].
2676     ColorAttachmentResolveMultisampled {
2677         attachment_index: u32,
2678     },
2679 
2680     /// A color attachment has a `samples` value that is different from the first
2681     /// color attachment.
2682     ColorAttachmentSamplesMismatch {
2683         attachment_index: u32,
2684     },
2685 
2686     /// A color attachment with a resolve attachment has a `samples` value of
2687     /// [`SampleCount::Sample1`].
2688     ColorAttachmentWithResolveNotMultisampled {
2689         attachment_index: u32,
2690     },
2691 
2692     /// The contents `SubpassContents::SecondaryCommandBuffers` is not allowed inside a secondary
2693     /// command buffer.
2694     ContentsForbiddenInSecondaryCommandBuffer,
2695 
2696     /// The depth attachment has a format that does not support that usage.
2697     DepthAttachmentFormatUsageNotSupported,
2698 
2699     /// The depth attachment has a layout that is not supported.
2700     DepthAttachmentLayoutInvalid,
2701 
2702     /// The depth attachment is missing the `depth_stencil_attachment` usage.
2703     DepthAttachmentMissingUsage,
2704 
2705     /// The depth resolve attachment has a `format` value different from the corresponding depth
2706     /// attachment.
2707     DepthAttachmentResolveFormatMismatch,
2708 
2709     /// The depth resolve attachment has a layout that is not supported.
2710     DepthAttachmentResolveLayoutInvalid,
2711 
2712     /// The depth resolve attachment has a resolve mode that is not supported.
2713     DepthAttachmentResolveModeNotSupported,
2714 
2715     /// The depth resolve attachment has a `samples` value other than [`SampleCount::Sample1`].
2716     DepthAttachmentResolveMultisampled,
2717 
2718     /// The depth attachment has a `samples` value that is different from the first
2719     /// color attachment.
2720     DepthAttachmentSamplesMismatch,
2721 
2722     /// The depth attachment has a resolve attachment and has a `samples` value of
2723     /// [`SampleCount::Sample1`].
2724     DepthAttachmentWithResolveNotMultisampled,
2725 
2726     /// The depth and stencil attachments have different image views.
2727     DepthStencilAttachmentImageViewMismatch,
2728 
2729     /// The depth and stencil resolve attachments have different image views.
2730     DepthStencilAttachmentResolveImageViewMismatch,
2731 
2732     /// The combination of depth and stencil resolve modes is not supported by the device.
2733     DepthStencilAttachmentResolveModesNotSupported,
2734 
2735     /// Operation forbidden inside a render pass.
2736     ForbiddenInsideRenderPass,
2737 
2738     /// Operation forbidden outside a render pass.
2739     ForbiddenOutsideRenderPass,
2740 
2741     /// Operation forbidden inside a render pass instance that was begun with `begin_rendering`.
2742     ForbiddenWithBeginRendering,
2743 
2744     /// Operation forbidden inside a render pass instance that was begun with `begin_render_pass`.
2745     ForbiddenWithBeginRenderPass,
2746 
2747     /// Operation forbidden inside a render pass instance that is inherited by a secondary command
2748     /// buffer.
2749     ForbiddenWithInheritedRenderPass,
2750 
2751     /// Operation forbidden inside a render subpass with the specified contents.
2752     ForbiddenWithSubpassContents {
2753         contents: SubpassContents,
2754     },
2755 
2756     /// The framebuffer is not compatible with the render pass.
2757     FramebufferNotCompatible,
2758 
2759     /// The `max_color_attachments` limit has been exceeded.
2760     MaxColorAttachmentsExceeded {
2761         color_attachment_count: u32,
2762         max: u32,
2763     },
2764 
2765     /// The `max_multiview_view_count` limit has been exceeded.
2766     MaxMultiviewViewCountExceeded {
2767         view_count: u32,
2768         max: u32,
2769     },
2770 
2771     /// The render pass uses multiview, but `layer_count` was not 0 or 1.
2772     MultiviewLayersInvalid,
2773 
2774     /// The render pass uses multiview, and in a clear rectangle, `array_layers` was not `0..1`.
2775     MultiviewRectArrayLayersInvalid {
2776         rect_index: usize,
2777     },
2778 
2779     /// Tried to advance to the next subpass, but there are no subpasses remaining in the render
2780     /// pass.
2781     NoSubpassesRemaining {
2782         current_subpass: u32,
2783     },
2784 
2785     /// The queue family doesn't allow this operation.
2786     NotSupportedByQueueFamily,
2787 
2788     /// A query is active that conflicts with the current operation.
2789     QueryIsActive,
2790 
2791     /// A clear rectangle's `array_layers` is empty.
2792     RectArrayLayersEmpty {
2793         rect_index: usize,
2794     },
2795 
2796     /// A clear rectangle's `array_layers` is outside the range of layers of the attachments.
2797     RectArrayLayersOutOfBounds {
2798         rect_index: usize,
2799     },
2800 
2801     /// A clear rectangle's `extent` is zero.
2802     RectExtentZero {
2803         rect_index: usize,
2804     },
2805 
2806     /// A clear rectangle's `offset` and `extent` are outside the render area of the render pass
2807     /// instance.
2808     RectOutOfBounds {
2809         rect_index: usize,
2810     },
2811 
2812     /// The render area's `offset` and `extent` are outside the extent of the framebuffer.
2813     RenderAreaOutOfBounds,
2814 
2815     /// The stencil attachment has a format that does not support that usage.
2816     StencilAttachmentFormatUsageNotSupported,
2817 
2818     /// The stencil attachment has a layout that is not supported.
2819     StencilAttachmentLayoutInvalid,
2820 
2821     /// The stencil attachment is missing the `depth_stencil_attachment` usage.
2822     StencilAttachmentMissingUsage,
2823 
2824     /// The stencil resolve attachment has a `format` value different from the corresponding stencil
2825     /// attachment.
2826     StencilAttachmentResolveFormatMismatch,
2827 
2828     /// The stencil resolve attachment has a layout that is not supported.
2829     StencilAttachmentResolveLayoutInvalid,
2830 
2831     /// The stencil resolve attachment has a resolve mode that is not supported.
2832     StencilAttachmentResolveModeNotSupported,
2833 
2834     /// The stencil resolve attachment has a `samples` value other than [`SampleCount::Sample1`].
2835     StencilAttachmentResolveMultisampled,
2836 
2837     /// The stencil attachment has a `samples` value that is different from the first
2838     /// color attachment or the depth attachment.
2839     StencilAttachmentSamplesMismatch,
2840 
2841     /// The stencil attachment has a resolve attachment and has a `samples` value of
2842     /// [`SampleCount::Sample1`].
2843     StencilAttachmentWithResolveNotMultisampled,
2844 
2845     /// Tried to end a render pass with subpasses still remaining in the render pass.
2846     SubpassesRemaining {
2847         current_subpass: u32,
2848         remaining_subpasses: u32,
2849     },
2850 }
2851 
2852 impl Error for RenderPassError {
source(&self) -> Option<&(dyn Error + 'static)>2853     fn source(&self) -> Option<&(dyn Error + 'static)> {
2854         match self {
2855             Self::SyncCommandBufferBuilderError(err) => Some(err),
2856             _ => None,
2857         }
2858     }
2859 }
2860 
2861 impl Display for RenderPassError {
fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError>2862     fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
2863         match self {
2864             Self::SyncCommandBufferBuilderError(_) => write!(f, "a SyncCommandBufferBuilderError"),
2865             Self::RequirementNotMet {
2866                 required_for,
2867                 requires_one_of,
2868             } => write!(
2869                 f,
2870                 "a requirement was not met for: {}; requires one of: {}",
2871                 required_for, requires_one_of,
2872             ),
2873             Self::AttachmentImageMissingUsage {
2874                 attachment_index,
2875                 usage,
2876             } => write!(
2877                 f,
2878                 "the framebuffer image attached to attachment index {} did not have the required \
2879                 usage {} enabled",
2880                 attachment_index, usage,
2881             ),
2882             Self::AutoExtentAttachmentsEmpty => write!(
2883                 f,
2884                 "one of the elements of `render_pass_extent` is zero, but no attachment images \
2885                 were given to calculate the extent from",
2886             ),
2887             Self::AutoLayersAttachmentsEmpty => write!(
2888                 f,
2889                 "`layer_count` is zero, but no attachment images were given to calculate the \
2890                 number of layers from",
2891             ),
2892             Self::ClearAttachmentNotCompatible {
2893                 clear_attachment,
2894                 attachment_format,
2895             } => write!(
2896                 f,
2897                 "a clear attachment value ({:?}) is not compatible with the attachment's format \
2898                 ({:?})",
2899                 clear_attachment, attachment_format,
2900             ),
2901             Self::ClearValueMissing { attachment_index } => write!(
2902                 f,
2903                 "a clear value for render pass attachment {} is missing",
2904                 attachment_index,
2905             ),
2906             Self::ClearValueNotCompatible {
2907                 clear_value,
2908                 attachment_index,
2909                 attachment_format,
2910             } => write!(
2911                 f,
2912                 "a clear value ({:?}) provided for render pass attachment {} is not compatible \
2913                 with the attachment's format ({:?})",
2914                 clear_value, attachment_index, attachment_format,
2915             ),
2916             Self::ColorAttachmentIndexOutOfRange {
2917                 color_attachment_index,
2918                 num_color_attachments,
2919             } => write!(
2920                 f,
2921                 "an attachment clear value specifies a `color_attachment` index {} that is not \
2922                 less than the number of color attachments in the subpass ({})",
2923                 color_attachment_index, num_color_attachments,
2924             ),
2925             Self::ColorAttachmentLayoutInvalid { attachment_index } => write!(
2926                 f,
2927                 "color attachment {} has a layout that is not supported",
2928                 attachment_index,
2929             ),
2930             Self::ColorAttachmentMissingUsage { attachment_index } => write!(
2931                 f,
2932                 "color attachment {} is missing the `color_attachment` usage",
2933                 attachment_index,
2934             ),
2935             Self::ColorAttachmentResolveFormatMismatch { attachment_index } => write!(
2936                 f,
2937                 "color attachment {} has a `format` value different from the corresponding color \
2938                 attachment",
2939                 attachment_index,
2940             ),
2941             Self::ColorAttachmentResolveLayoutInvalid { attachment_index } => write!(
2942                 f,
2943                 "color resolve attachment {} has a layout that is not supported",
2944                 attachment_index,
2945             ),
2946             Self::ColorAttachmentResolveModeNotSupported { attachment_index } => write!(
2947                 f,
2948                 "color resolve attachment {} has a resolve mode that is not supported",
2949                 attachment_index,
2950             ),
2951             Self::ColorAttachmentResolveMultisampled { attachment_index } => write!(
2952                 f,
2953                 "color resolve attachment {} has a `samples` value other than \
2954                 `SampleCount::Sample1`",
2955                 attachment_index,
2956             ),
2957             Self::ColorAttachmentSamplesMismatch { attachment_index } => write!(
2958                 f,
2959                 "color attachment {} has a `samples` value that is different from the first color \
2960                 attachment",
2961                 attachment_index,
2962             ),
2963             Self::ColorAttachmentWithResolveNotMultisampled { attachment_index } => write!(
2964                 f,
2965                 "color attachment {} with a resolve attachment has a `samples` value of \
2966                 `SampleCount::Sample1`",
2967                 attachment_index,
2968             ),
2969             Self::ContentsForbiddenInSecondaryCommandBuffer => write!(
2970                 f,
2971                 "the contents `SubpassContents::SecondaryCommandBuffers` is not allowed inside a \
2972                 secondary command buffer",
2973             ),
2974             Self::DepthAttachmentFormatUsageNotSupported => write!(
2975                 f,
2976                 "the depth attachment has a format that does not support that usage",
2977             ),
2978             Self::DepthAttachmentLayoutInvalid => {
2979                 write!(f, "the depth attachment has a layout that is not supported")
2980             }
2981             Self::DepthAttachmentMissingUsage => write!(
2982                 f,
2983                 "the depth attachment is missing the `depth_stencil_attachment` usage",
2984             ),
2985             Self::DepthAttachmentResolveFormatMismatch => write!(
2986                 f,
2987                 "the depth resolve attachment has a `format` value different from the \
2988                 corresponding depth attachment",
2989             ),
2990             Self::DepthAttachmentResolveLayoutInvalid => write!(
2991                 f,
2992                 "the depth resolve attachment has a layout that is not supported",
2993             ),
2994             Self::DepthAttachmentResolveModeNotSupported => write!(
2995                 f,
2996                 "the depth resolve attachment has a resolve mode that is not supported",
2997             ),
2998             Self::DepthAttachmentResolveMultisampled => write!(
2999                 f,
3000                 "the depth resolve attachment has a `samples` value other than \
3001                 `SampleCount::Sample1`",
3002             ),
3003             Self::DepthAttachmentSamplesMismatch => write!(
3004                 f,
3005                 "the depth attachment has a `samples` value that is different from the first color \
3006                 attachment",
3007             ),
3008             Self::DepthAttachmentWithResolveNotMultisampled => write!(
3009                 f,
3010                 "the depth attachment has a resolve attachment and has a `samples` value of \
3011                 `SampleCount::Sample1`",
3012             ),
3013             Self::DepthStencilAttachmentImageViewMismatch => write!(
3014                 f,
3015                 "the depth and stencil attachments have different image views",
3016             ),
3017             Self::DepthStencilAttachmentResolveImageViewMismatch => write!(
3018                 f,
3019                 "the depth and stencil resolve attachments have different image views",
3020             ),
3021             Self::DepthStencilAttachmentResolveModesNotSupported => write!(
3022                 f,
3023                 "the combination of depth and stencil resolve modes is not supported by the device",
3024             ),
3025             Self::ForbiddenInsideRenderPass => {
3026                 write!(f, "operation forbidden inside a render pass")
3027             }
3028             Self::ForbiddenOutsideRenderPass => {
3029                 write!(f, "operation forbidden outside a render pass")
3030             }
3031             Self::ForbiddenWithBeginRendering => write!(
3032                 f,
3033                 "operation forbidden inside a render pass instance that was begun with \
3034                 `begin_rendering`",
3035             ),
3036             Self::ForbiddenWithBeginRenderPass => write!(
3037                 f,
3038                 "operation forbidden inside a render pass instance that was begun with \
3039                 `begin_render_pass`",
3040             ),
3041             Self::ForbiddenWithInheritedRenderPass => write!(
3042                 f,
3043                 "operation forbidden inside a render pass instance that is inherited by a \
3044                 secondary command buffer",
3045             ),
3046             Self::ForbiddenWithSubpassContents {
3047                 contents: subpass_contents,
3048             } => write!(
3049                 f,
3050                 "operation forbidden inside a render subpass with contents {:?}",
3051                 subpass_contents,
3052             ),
3053             Self::FramebufferNotCompatible => {
3054                 write!(f, "the framebuffer is not compatible with the render pass")
3055             }
3056             Self::MaxColorAttachmentsExceeded { .. } => {
3057                 write!(f, "the `max_color_attachments` limit has been exceeded")
3058             }
3059             Self::MaxMultiviewViewCountExceeded { .. } => {
3060                 write!(f, "the `max_multiview_view_count` limit has been exceeded")
3061             }
3062             Self::MultiviewLayersInvalid => write!(
3063                 f,
3064                 "the render pass uses multiview, but `layer_count` was not 0 or 1",
3065             ),
3066             Self::MultiviewRectArrayLayersInvalid { rect_index } => write!(
3067                 f,
3068                 "the render pass uses multiview, and in clear rectangle index {}, `array_layers` \
3069                 was not `0..1`",
3070                 rect_index,
3071             ),
3072             Self::NoSubpassesRemaining { current_subpass } => write!(
3073                 f,
3074                 "tried to advance to the next subpass after subpass {}, but there are no subpasses \
3075                 remaining in the render pass",
3076                 current_subpass,
3077             ),
3078             Self::NotSupportedByQueueFamily => {
3079                 write!(f, "the queue family doesn't allow this operation")
3080             }
3081             Self::QueryIsActive => write!(
3082                 f,
3083                 "a query is active that conflicts with the current operation",
3084             ),
3085             Self::RectArrayLayersEmpty { rect_index } => write!(
3086                 f,
3087                 "clear rectangle index {} `array_layers` is empty",
3088                 rect_index,
3089             ),
3090             Self::RectArrayLayersOutOfBounds { rect_index } => write!(
3091                 f,
3092                 "clear rectangle index {} `array_layers` is outside the range of layers of the \
3093                 attachments",
3094                 rect_index,
3095             ),
3096             Self::RectExtentZero { rect_index } => {
3097                 write!(f, "clear rectangle index {} `extent` is zero", rect_index)
3098             }
3099             Self::RectOutOfBounds { rect_index } => write!(
3100                 f,
3101                 "clear rectangle index {} `offset` and `extent` are outside the render area of the \
3102                 render pass instance",
3103                 rect_index,
3104             ),
3105             Self::RenderAreaOutOfBounds => write!(
3106                 f,
3107                 "the render area's `offset` and `extent` are outside the extent of the framebuffer",
3108             ),
3109             Self::StencilAttachmentFormatUsageNotSupported => write!(
3110                 f,
3111                 "the stencil attachment has a format that does not support that usage",
3112             ),
3113             Self::StencilAttachmentLayoutInvalid => write!(
3114                 f,
3115                 "the stencil attachment has a layout that is not supported",
3116             ),
3117             Self::StencilAttachmentMissingUsage => write!(
3118                 f,
3119                 "the stencil attachment is missing the `depth_stencil_attachment` usage",
3120             ),
3121             Self::StencilAttachmentResolveFormatMismatch => write!(
3122                 f,
3123                 "the stencil resolve attachment has a `format` value different from the \
3124                 corresponding stencil attachment",
3125             ),
3126             Self::StencilAttachmentResolveLayoutInvalid => write!(
3127                 f,
3128                 "the stencil resolve attachment has a layout that is not supported",
3129             ),
3130             Self::StencilAttachmentResolveModeNotSupported => write!(
3131                 f,
3132                 "the stencil resolve attachment has a resolve mode that is not supported",
3133             ),
3134             Self::StencilAttachmentResolveMultisampled => write!(
3135                 f,
3136                 "the stencil resolve attachment has a `samples` value other than \
3137                 `SampleCount::Sample1`",
3138             ),
3139             Self::StencilAttachmentSamplesMismatch => write!(
3140                 f,
3141                 "the stencil attachment has a `samples` value that is different from the first \
3142                 color attachment",
3143             ),
3144             Self::StencilAttachmentWithResolveNotMultisampled => write!(
3145                 f,
3146                 "the stencil attachment has a resolve attachment and has a `samples` value of \
3147                 `SampleCount::Sample1`",
3148             ),
3149             Self::SubpassesRemaining {
3150                 current_subpass,
3151                 remaining_subpasses,
3152             } => write!(
3153                 f,
3154                 "tried to end a render pass at subpass {}, with {} subpasses still remaining in \
3155                 the render pass",
3156                 current_subpass, remaining_subpasses,
3157             ),
3158         }
3159     }
3160 }
3161 
3162 impl From<SyncCommandBufferBuilderError> for RenderPassError {
from(err: SyncCommandBufferBuilderError) -> Self3163     fn from(err: SyncCommandBufferBuilderError) -> Self {
3164         Self::SyncCommandBufferBuilderError(err)
3165     }
3166 }
3167 
3168 impl From<RequirementNotMet> for RenderPassError {
from(err: RequirementNotMet) -> Self3169     fn from(err: RequirementNotMet) -> Self {
3170         Self::RequirementNotMet {
3171             required_for: err.required_for,
3172             requires_one_of: err.requires_one_of,
3173         }
3174     }
3175 }
3176