• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 super::{
11     BeginRenderPassState, BeginRenderingState, ClearAttachment, ClearRect, CommandBufferBuilder,
12     RenderPassBeginInfo, RenderPassError, RenderPassState, RenderPassStateAttachmentInfo,
13     RenderPassStateAttachmentResolveInfo, RenderPassStateAttachments, RenderPassStateType,
14     RenderingAttachmentInfo, RenderingAttachmentResolveInfo, RenderingInfo, ResourcesState,
15 };
16 use crate::{
17     command_buffer::{
18         allocator::CommandBufferAllocator, PrimaryCommandBuffer, ResourceInCommand, ResourceUseRef,
19         SubpassContents,
20     },
21     device::{DeviceOwned, QueueFlags},
22     format::{ClearColorValue, ClearValue, NumericType},
23     image::{ImageAspects, ImageLayout, ImageUsage, SampleCount},
24     pipeline::graphics::render_pass::PipelineRenderingCreateInfo,
25     render_pass::{AttachmentDescription, LoadOp, ResolveMode, SubpassDescription},
26     sync::PipelineStageAccess,
27     RequiresOneOf, Version, VulkanObject,
28 };
29 use smallvec::SmallVec;
30 use std::cmp::min;
31 
32 impl<A> CommandBufferBuilder<PrimaryCommandBuffer<A::Alloc>, A>
33 where
34     A: CommandBufferAllocator,
35 {
36     /// Begins a render pass using a render pass object and framebuffer.
37     ///
38     /// You must call this or `begin_rendering` before you can record draw commands.
39     ///
40     /// `contents` specifies what kinds of commands will be recorded in the render pass, either
41     /// draw commands or executions of secondary command buffers.
42     ///
43     /// # Safety
44     ///
45     /// - Appropriate synchronization must be provided for all images
46     ///   that are accessed by the command.
47     /// - All images that are accessed by the command must be in the expected image layout.
48     #[inline]
begin_render_pass( &mut self, render_pass_begin_info: RenderPassBeginInfo, contents: SubpassContents, ) -> Result<&mut Self, RenderPassError>49     pub unsafe fn begin_render_pass(
50         &mut self,
51         render_pass_begin_info: RenderPassBeginInfo,
52         contents: SubpassContents,
53     ) -> Result<&mut Self, RenderPassError> {
54         self.validate_begin_render_pass(&render_pass_begin_info, contents)?;
55 
56         unsafe { Ok(self.begin_render_pass_unchecked(render_pass_begin_info, contents)) }
57     }
58 
validate_begin_render_pass( &self, render_pass_begin_info: &RenderPassBeginInfo, contents: SubpassContents, ) -> Result<(), RenderPassError>59     fn validate_begin_render_pass(
60         &self,
61         render_pass_begin_info: &RenderPassBeginInfo,
62         contents: SubpassContents,
63     ) -> Result<(), RenderPassError> {
64         let device = self.device();
65 
66         // VUID-VkSubpassBeginInfo-contents-parameter
67         contents.validate_device(device)?;
68 
69         let queue_family_properties = self.queue_family_properties();
70 
71         // VUID-vkCmdBeginRenderPass2-commandBuffer-cmdpool
72         if !queue_family_properties
73             .queue_flags
74             .intersects(QueueFlags::GRAPHICS)
75         {
76             return Err(RenderPassError::NotSupportedByQueueFamily);
77         }
78 
79         // VUID-vkCmdBeginRenderPass2-renderpass
80         if self.builder_state.render_pass.is_some() {
81             return Err(RenderPassError::ForbiddenInsideRenderPass);
82         }
83 
84         let RenderPassBeginInfo {
85             render_pass,
86             framebuffer,
87             render_area_offset,
88             render_area_extent,
89             clear_values,
90             _ne: _,
91         } = render_pass_begin_info;
92 
93         // VUID-VkRenderPassBeginInfo-commonparent
94         // VUID-vkCmdBeginRenderPass2-framebuffer-02779
95         assert_eq!(device, framebuffer.device());
96 
97         // VUID-VkRenderPassBeginInfo-renderPass-00904
98         if !render_pass.is_compatible_with(framebuffer.render_pass()) {
99             return Err(RenderPassError::FramebufferNotCompatible);
100         }
101 
102         for i in 0..2 {
103             // VUID-VkRenderPassBeginInfo-pNext-02852
104             // VUID-VkRenderPassBeginInfo-pNext-02853
105             if render_area_offset[i] + render_area_extent[i] > framebuffer.extent()[i] {
106                 return Err(RenderPassError::RenderAreaOutOfBounds);
107             }
108         }
109 
110         for (attachment_index, (attachment_desc, image_view)) in render_pass
111             .attachments()
112             .iter()
113             .zip(framebuffer.attachments())
114             .enumerate()
115         {
116             let attachment_index = attachment_index as u32;
117             let &AttachmentDescription {
118                 initial_layout,
119                 final_layout,
120                 ..
121             } = attachment_desc;
122 
123             for layout in [initial_layout, final_layout] {
124                 match layout {
125                     ImageLayout::ColorAttachmentOptimal => {
126                         // VUID-vkCmdBeginRenderPass2-initialLayout-03094
127                         if !image_view.usage().intersects(ImageUsage::COLOR_ATTACHMENT) {
128                             return Err(RenderPassError::AttachmentImageMissingUsage {
129                                 attachment_index,
130                                 usage: "color_attachment",
131                             });
132                         }
133                     }
134                     ImageLayout::DepthReadOnlyStencilAttachmentOptimal
135                     | ImageLayout::DepthAttachmentStencilReadOnlyOptimal
136                     | ImageLayout::DepthStencilAttachmentOptimal
137                     | ImageLayout::DepthStencilReadOnlyOptimal => {
138                         // VUID-vkCmdBeginRenderPass2-initialLayout-03096
139                         if !image_view
140                             .usage()
141                             .intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
142                         {
143                             return Err(RenderPassError::AttachmentImageMissingUsage {
144                                 attachment_index,
145                                 usage: "depth_stencil_attachment",
146                             });
147                         }
148                     }
149                     ImageLayout::ShaderReadOnlyOptimal => {
150                         // VUID-vkCmdBeginRenderPass2-initialLayout-03097
151                         if !image_view
152                             .usage()
153                             .intersects(ImageUsage::SAMPLED | ImageUsage::INPUT_ATTACHMENT)
154                         {
155                             return Err(RenderPassError::AttachmentImageMissingUsage {
156                                 attachment_index,
157                                 usage: "sampled or input_attachment",
158                             });
159                         }
160                     }
161                     ImageLayout::TransferSrcOptimal => {
162                         // VUID-vkCmdBeginRenderPass2-initialLayout-03098
163                         if !image_view.usage().intersects(ImageUsage::TRANSFER_SRC) {
164                             return Err(RenderPassError::AttachmentImageMissingUsage {
165                                 attachment_index,
166                                 usage: "transfer_src",
167                             });
168                         }
169                     }
170                     ImageLayout::TransferDstOptimal => {
171                         // VUID-vkCmdBeginRenderPass2-initialLayout-03099
172                         if !image_view.usage().intersects(ImageUsage::TRANSFER_DST) {
173                             return Err(RenderPassError::AttachmentImageMissingUsage {
174                                 attachment_index,
175                                 usage: "transfer_dst",
176                             });
177                         }
178                     }
179                     _ => (),
180                 }
181             }
182         }
183 
184         for subpass_desc in render_pass.subpasses() {
185             let SubpassDescription {
186                 view_mask: _,
187                 input_attachments,
188                 color_attachments,
189                 resolve_attachments,
190                 depth_stencil_attachment,
191                 preserve_attachments: _,
192                 _ne: _,
193             } = subpass_desc;
194 
195             for atch_ref in (input_attachments.iter())
196                 .chain(color_attachments)
197                 .chain(resolve_attachments)
198                 .chain([depth_stencil_attachment])
199                 .flatten()
200             {
201                 let image_view = &framebuffer.attachments()[atch_ref.attachment as usize];
202 
203                 match atch_ref.layout {
204                     ImageLayout::ColorAttachmentOptimal => {
205                         // VUID-vkCmdBeginRenderPass2-initialLayout-03094
206                         if !image_view.usage().intersects(ImageUsage::COLOR_ATTACHMENT) {
207                             return Err(RenderPassError::AttachmentImageMissingUsage {
208                                 attachment_index: atch_ref.attachment,
209                                 usage: "color_attachment",
210                             });
211                         }
212                     }
213                     ImageLayout::DepthReadOnlyStencilAttachmentOptimal
214                     | ImageLayout::DepthAttachmentStencilReadOnlyOptimal
215                     | ImageLayout::DepthStencilAttachmentOptimal
216                     | ImageLayout::DepthStencilReadOnlyOptimal => {
217                         // VUID-vkCmdBeginRenderPass2-initialLayout-03096
218                         if !image_view
219                             .usage()
220                             .intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
221                         {
222                             return Err(RenderPassError::AttachmentImageMissingUsage {
223                                 attachment_index: atch_ref.attachment,
224                                 usage: "depth_stencil_attachment",
225                             });
226                         }
227                     }
228                     ImageLayout::ShaderReadOnlyOptimal => {
229                         // VUID-vkCmdBeginRenderPass2-initialLayout-03097
230                         if !image_view
231                             .usage()
232                             .intersects(ImageUsage::SAMPLED | ImageUsage::INPUT_ATTACHMENT)
233                         {
234                             return Err(RenderPassError::AttachmentImageMissingUsage {
235                                 attachment_index: atch_ref.attachment,
236                                 usage: "sampled or input_attachment",
237                             });
238                         }
239                     }
240                     ImageLayout::TransferSrcOptimal => {
241                         // VUID-vkCmdBeginRenderPass2-initialLayout-03098
242                         if !image_view.usage().intersects(ImageUsage::TRANSFER_SRC) {
243                             return Err(RenderPassError::AttachmentImageMissingUsage {
244                                 attachment_index: atch_ref.attachment,
245                                 usage: "transfer_src",
246                             });
247                         }
248                     }
249                     ImageLayout::TransferDstOptimal => {
250                         // VUID-vkCmdBeginRenderPass2-initialLayout-03099
251                         if !image_view.usage().intersects(ImageUsage::TRANSFER_DST) {
252                             return Err(RenderPassError::AttachmentImageMissingUsage {
253                                 attachment_index: atch_ref.attachment,
254                                 usage: "transfer_dst",
255                             });
256                         }
257                     }
258                     _ => (),
259                 }
260             }
261         }
262 
263         // VUID-VkRenderPassBeginInfo-clearValueCount-00902
264         if clear_values.len() < render_pass.attachments().len() {
265             return Err(RenderPassError::ClearValueMissing {
266                 attachment_index: clear_values.len() as u32,
267             });
268         }
269 
270         // VUID-VkRenderPassBeginInfo-clearValueCount-04962
271         for (attachment_index, (attachment_desc, &clear_value)) in render_pass
272             .attachments()
273             .iter()
274             .zip(clear_values)
275             .enumerate()
276         {
277             let attachment_index = attachment_index as u32;
278             let attachment_format = attachment_desc.format.unwrap();
279 
280             if attachment_desc.load_op == LoadOp::Clear
281                 || attachment_desc.stencil_load_op == LoadOp::Clear
282             {
283                 let clear_value = match clear_value {
284                     Some(x) => x,
285                     None => return Err(RenderPassError::ClearValueMissing { attachment_index }),
286                 };
287 
288                 if let (Some(numeric_type), LoadOp::Clear) =
289                     (attachment_format.type_color(), attachment_desc.load_op)
290                 {
291                     match numeric_type {
292                         NumericType::SFLOAT
293                         | NumericType::UFLOAT
294                         | NumericType::SNORM
295                         | NumericType::UNORM
296                         | NumericType::SSCALED
297                         | NumericType::USCALED
298                         | NumericType::SRGB => {
299                             if !matches!(clear_value, ClearValue::Float(_)) {
300                                 return Err(RenderPassError::ClearValueNotCompatible {
301                                     clear_value,
302                                     attachment_index,
303                                     attachment_format,
304                                 });
305                             }
306                         }
307                         NumericType::SINT => {
308                             if !matches!(clear_value, ClearValue::Int(_)) {
309                                 return Err(RenderPassError::ClearValueNotCompatible {
310                                     clear_value,
311                                     attachment_index,
312                                     attachment_format,
313                                 });
314                             }
315                         }
316                         NumericType::UINT => {
317                             if !matches!(clear_value, ClearValue::Uint(_)) {
318                                 return Err(RenderPassError::ClearValueNotCompatible {
319                                     clear_value,
320                                     attachment_index,
321                                     attachment_format,
322                                 });
323                             }
324                         }
325                     }
326                 } else {
327                     let attachment_aspects = attachment_format.aspects();
328                     let need_depth = attachment_aspects.intersects(ImageAspects::DEPTH)
329                         && attachment_desc.load_op == LoadOp::Clear;
330                     let need_stencil = attachment_aspects.intersects(ImageAspects::STENCIL)
331                         && attachment_desc.stencil_load_op == LoadOp::Clear;
332 
333                     if need_depth && need_stencil {
334                         if !matches!(clear_value, ClearValue::DepthStencil(_)) {
335                             return Err(RenderPassError::ClearValueNotCompatible {
336                                 clear_value,
337                                 attachment_index,
338                                 attachment_format,
339                             });
340                         }
341                     } else if need_depth {
342                         if !matches!(clear_value, ClearValue::Depth(_)) {
343                             return Err(RenderPassError::ClearValueNotCompatible {
344                                 clear_value,
345                                 attachment_index,
346                                 attachment_format,
347                             });
348                         }
349                     } else if need_stencil {
350                         if !matches!(clear_value, ClearValue::Stencil(_)) {
351                             return Err(RenderPassError::ClearValueNotCompatible {
352                                 clear_value,
353                                 attachment_index,
354                                 attachment_format,
355                             });
356                         }
357                     }
358                 }
359             }
360         }
361 
362         // VUID-vkCmdBeginRenderPass2-initialLayout-03100
363         // TODO:
364 
365         // VUID-vkCmdBeginRenderPass2-srcStageMask-06453
366         // TODO:
367 
368         // VUID-vkCmdBeginRenderPass2-dstStageMask-06454
369         // TODO:
370 
371         // VUID-vkCmdBeginRenderPass2-framebuffer-02533
372         // 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
373         // attachment to be written to, both attachments must have had the VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT set
374 
375         // TODO: sync check
376 
377         Ok(())
378     }
379 
380     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
begin_render_pass_unchecked( &mut self, render_pass_begin_info: RenderPassBeginInfo, contents: SubpassContents, ) -> &mut Self381     pub unsafe fn begin_render_pass_unchecked(
382         &mut self,
383         render_pass_begin_info: RenderPassBeginInfo,
384         contents: SubpassContents,
385     ) -> &mut Self {
386         let RenderPassBeginInfo {
387             render_pass,
388             framebuffer,
389             render_area_offset,
390             render_area_extent,
391             clear_values,
392             _ne: _,
393         } = render_pass_begin_info;
394 
395         let clear_values_vk: SmallVec<[_; 4]> = clear_values
396             .iter()
397             .copied()
398             .map(|clear_value| clear_value.map(Into::into).unwrap_or_default())
399             .collect();
400 
401         let render_pass_begin_info = ash::vk::RenderPassBeginInfo {
402             render_pass: render_pass.handle(),
403             framebuffer: framebuffer.handle(),
404             render_area: ash::vk::Rect2D {
405                 offset: ash::vk::Offset2D {
406                     x: render_area_offset[0] as i32,
407                     y: render_area_offset[1] as i32,
408                 },
409                 extent: ash::vk::Extent2D {
410                     width: render_area_extent[0],
411                     height: render_area_extent[1],
412                 },
413             },
414             clear_value_count: clear_values_vk.len() as u32,
415             p_clear_values: clear_values_vk.as_ptr(),
416             ..Default::default()
417         };
418 
419         let subpass_begin_info = ash::vk::SubpassBeginInfo {
420             contents: contents.into(),
421             ..Default::default()
422         };
423 
424         let fns = self.device().fns();
425 
426         if self.device().api_version() >= Version::V1_2
427             || self.device().enabled_extensions().khr_create_renderpass2
428         {
429             if self.device().api_version() >= Version::V1_2 {
430                 (fns.v1_2.cmd_begin_render_pass2)(
431                     self.handle(),
432                     &render_pass_begin_info,
433                     &subpass_begin_info,
434                 );
435             } else {
436                 (fns.khr_create_renderpass2.cmd_begin_render_pass2_khr)(
437                     self.handle(),
438                     &render_pass_begin_info,
439                     &subpass_begin_info,
440                 );
441             }
442         } else {
443             debug_assert!(subpass_begin_info.p_next.is_null());
444 
445             (fns.v1_0.cmd_begin_render_pass)(
446                 self.handle(),
447                 &render_pass_begin_info,
448                 subpass_begin_info.contents,
449             );
450         }
451 
452         let command_index = self.next_command_index;
453         let command_name = "begin_render_pass";
454 
455         // Advance to first subpass
456         {
457             let subpass = render_pass.clone().first_subpass();
458             self.builder_state.render_pass = Some(RenderPassState {
459                 contents,
460                 render_area_offset,
461                 render_area_extent,
462 
463                 rendering_info: PipelineRenderingCreateInfo::from_subpass(&subpass),
464                 attachments: Some(RenderPassStateAttachments::from_subpass(
465                     &subpass,
466                     &framebuffer,
467                 )),
468 
469                 render_pass: BeginRenderPassState {
470                     subpass,
471                     framebuffer: Some(framebuffer.clone()),
472                 }
473                 .into(),
474             });
475         }
476 
477         // Start of first subpass
478         {
479             // TODO: Apply barriers and layout transitions
480 
481             let render_pass_state = self.builder_state.render_pass.as_ref().unwrap();
482             record_subpass_attachments_load(
483                 &mut self.resources_usage_state,
484                 command_index,
485                 command_name,
486                 render_pass_state,
487             );
488         }
489 
490         self.resources.push(Box::new(render_pass));
491         self.resources.push(Box::new(framebuffer));
492 
493         self.next_command_index += 1;
494         self
495     }
496 
497     /// Advances to the next subpass of the render pass previously begun with `begin_render_pass`.
498     ///
499     /// # Safety
500     ///
501     /// - Appropriate synchronization must be provided for all images
502     ///   that are accessed by the command.
503     /// - All images that are accessed by the command must be in the expected image layout.
504     #[inline]
next_subpass( &mut self, contents: SubpassContents, ) -> Result<&mut Self, RenderPassError>505     pub unsafe fn next_subpass(
506         &mut self,
507         contents: SubpassContents,
508     ) -> Result<&mut Self, RenderPassError> {
509         self.validate_next_subpass(contents)?;
510 
511         unsafe { Ok(self.next_subpass_unchecked(contents)) }
512     }
513 
validate_next_subpass(&self, contents: SubpassContents) -> Result<(), RenderPassError>514     fn validate_next_subpass(&self, contents: SubpassContents) -> Result<(), RenderPassError> {
515         let device = self.device();
516 
517         // VUID-VkSubpassBeginInfo-contents-parameter
518         contents.validate_device(device)?;
519 
520         // VUID-vkCmdNextSubpass2-renderpass
521         let render_pass_state = self
522             .builder_state
523             .render_pass
524             .as_ref()
525             .ok_or(RenderPassError::ForbiddenOutsideRenderPass)?;
526 
527         let begin_render_pass_state = match &render_pass_state.render_pass {
528             RenderPassStateType::BeginRenderPass(state) => state,
529             RenderPassStateType::BeginRendering(_) => {
530                 return Err(RenderPassError::ForbiddenWithBeginRendering)
531             }
532         };
533 
534         // VUID-vkCmdNextSubpass2-None-03102
535         if begin_render_pass_state.subpass.is_last_subpass() {
536             return Err(RenderPassError::NoSubpassesRemaining {
537                 current_subpass: begin_render_pass_state.subpass.index(),
538             });
539         }
540 
541         // VUID?
542         if self
543             .builder_state
544             .queries
545             .values()
546             .any(|state| state.in_subpass)
547         {
548             return Err(RenderPassError::QueryIsActive);
549         }
550 
551         // VUID-vkCmdNextSubpass2-commandBuffer-cmdpool
552         debug_assert!(self
553             .queue_family_properties()
554             .queue_flags
555             .intersects(QueueFlags::GRAPHICS));
556 
557         // VUID-vkCmdNextSubpass2-bufferlevel
558         // Ensured by the type of the impl block
559 
560         // TODO: sync check
561 
562         Ok(())
563     }
564 
565     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
next_subpass_unchecked(&mut self, contents: SubpassContents) -> &mut Self566     pub unsafe fn next_subpass_unchecked(&mut self, contents: SubpassContents) -> &mut Self {
567         let subpass_begin_info = ash::vk::SubpassBeginInfo {
568             contents: contents.into(),
569             ..Default::default()
570         };
571 
572         let subpass_end_info = ash::vk::SubpassEndInfo::default();
573 
574         let fns = self.device().fns();
575 
576         if self.device().api_version() >= Version::V1_2
577             || self.device().enabled_extensions().khr_create_renderpass2
578         {
579             if self.device().api_version() >= Version::V1_2 {
580                 (fns.v1_2.cmd_next_subpass2)(self.handle(), &subpass_begin_info, &subpass_end_info);
581             } else {
582                 (fns.khr_create_renderpass2.cmd_next_subpass2_khr)(
583                     self.handle(),
584                     &subpass_begin_info,
585                     &subpass_end_info,
586                 );
587             }
588         } else {
589             (fns.v1_0.cmd_next_subpass)(self.handle(), subpass_begin_info.contents);
590         }
591 
592         let command_index = self.next_command_index;
593         let command_name = "next_subpass";
594 
595         // End of previous subpass
596         {
597             let render_pass_state = self.builder_state.render_pass.as_ref().unwrap();
598             record_subpass_attachments_resolve(
599                 &mut self.resources_usage_state,
600                 command_index,
601                 command_name,
602                 render_pass_state,
603             );
604             record_subpass_attachments_store(
605                 &mut self.resources_usage_state,
606                 command_index,
607                 command_name,
608                 render_pass_state,
609             );
610         }
611 
612         // Advance to next subpass
613         {
614             let render_pass_state = self.builder_state.render_pass.as_mut().unwrap();
615             let begin_render_pass_state = match &mut render_pass_state.render_pass {
616                 RenderPassStateType::BeginRenderPass(x) => x,
617                 _ => unreachable!(),
618             };
619 
620             begin_render_pass_state.subpass.next_subpass();
621             render_pass_state.contents = contents;
622             render_pass_state.rendering_info =
623                 PipelineRenderingCreateInfo::from_subpass(&begin_render_pass_state.subpass);
624             render_pass_state.attachments = Some(RenderPassStateAttachments::from_subpass(
625                 &begin_render_pass_state.subpass,
626                 begin_render_pass_state.framebuffer.as_ref().unwrap(),
627             ));
628 
629             if render_pass_state.rendering_info.view_mask != 0 {
630                 // When multiview is enabled, at the beginning of each subpass, all
631                 // non-render pass state is undefined.
632                 self.builder_state = Default::default();
633             }
634         }
635 
636         // Start of next subpass
637         {
638             // TODO: Apply barriers and layout transitions
639 
640             let render_pass_state = self.builder_state.render_pass.as_ref().unwrap();
641             record_subpass_attachments_load(
642                 &mut self.resources_usage_state,
643                 command_index,
644                 command_name,
645                 render_pass_state,
646             );
647         }
648 
649         self.next_command_index += 1;
650         self
651     }
652 
653     /// Ends the render pass previously begun with `begin_render_pass`.
654     ///
655     /// This must be called after you went through all the subpasses.
656     ///
657     /// # Safety
658     ///
659     /// - Appropriate synchronization must be provided for all images
660     ///   that are accessed by the command.
661     /// - All images that are accessed by the command must be in the expected image layout.
662     #[inline]
end_render_pass(&mut self) -> Result<&mut Self, RenderPassError>663     pub unsafe fn end_render_pass(&mut self) -> Result<&mut Self, RenderPassError> {
664         self.validate_end_render_pass()?;
665 
666         unsafe { Ok(self.end_render_pass_unchecked()) }
667     }
668 
validate_end_render_pass(&self) -> Result<(), RenderPassError>669     fn validate_end_render_pass(&self) -> Result<(), RenderPassError> {
670         // VUID-vkCmdEndRenderPass2-renderpass
671         let render_pass_state = self
672             .builder_state
673             .render_pass
674             .as_ref()
675             .ok_or(RenderPassError::ForbiddenOutsideRenderPass)?;
676 
677         let begin_render_pass_state = match &render_pass_state.render_pass {
678             RenderPassStateType::BeginRenderPass(state) => state,
679             RenderPassStateType::BeginRendering(_) => {
680                 return Err(RenderPassError::ForbiddenWithBeginRendering)
681             }
682         };
683 
684         // VUID-vkCmdEndRenderPass2-None-03103
685         if !begin_render_pass_state.subpass.is_last_subpass() {
686             return Err(RenderPassError::SubpassesRemaining {
687                 current_subpass: begin_render_pass_state.subpass.index(),
688                 remaining_subpasses: begin_render_pass_state
689                     .subpass
690                     .render_pass()
691                     .subpasses()
692                     .len() as u32
693                     - begin_render_pass_state.subpass.index(),
694             });
695         }
696 
697         // VUID?
698         if self
699             .builder_state
700             .queries
701             .values()
702             .any(|state| state.in_subpass)
703         {
704             return Err(RenderPassError::QueryIsActive);
705         }
706 
707         // VUID-vkCmdEndRenderPass2-commandBuffer-cmdpool
708         debug_assert!(self
709             .queue_family_properties()
710             .queue_flags
711             .intersects(QueueFlags::GRAPHICS));
712 
713         // VUID-vkCmdEndRenderPass2-bufferlevel
714         // Ensured by the type of the impl block
715 
716         // TODO: sync check
717 
718         Ok(())
719     }
720 
721     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
end_render_pass_unchecked(&mut self) -> &mut Self722     pub unsafe fn end_render_pass_unchecked(&mut self) -> &mut Self {
723         let subpass_end_info = ash::vk::SubpassEndInfo::default();
724 
725         let fns = self.device().fns();
726 
727         if self.device().api_version() >= Version::V1_2
728             || self.device().enabled_extensions().khr_create_renderpass2
729         {
730             if self.device().api_version() >= Version::V1_2 {
731                 (fns.v1_2.cmd_end_render_pass2)(self.handle(), &subpass_end_info);
732             } else {
733                 (fns.khr_create_renderpass2.cmd_end_render_pass2_khr)(
734                     self.handle(),
735                     &subpass_end_info,
736                 );
737             }
738         } else {
739             (fns.v1_0.cmd_end_render_pass)(self.handle());
740         }
741 
742         let command_index = self.next_command_index;
743         let command_name = "end_render_pass";
744 
745         // End of last subpass
746         {
747             let render_pass_state = self.builder_state.render_pass.as_ref().unwrap();
748             record_subpass_attachments_resolve(
749                 &mut self.resources_usage_state,
750                 command_index,
751                 command_name,
752                 render_pass_state,
753             );
754             record_subpass_attachments_store(
755                 &mut self.resources_usage_state,
756                 command_index,
757                 command_name,
758                 render_pass_state,
759             );
760         }
761 
762         // TODO: Apply barriers and layout transitions
763 
764         self.builder_state.render_pass = None;
765 
766         self.next_command_index += 1;
767         self
768     }
769 }
770 
771 impl<L, A> CommandBufferBuilder<L, A>
772 where
773     A: CommandBufferAllocator,
774 {
775     /// Begins a render pass without a render pass object or framebuffer.
776     ///
777     /// You must call this or `begin_render_pass` before you can record draw commands.
778     ///
779     /// # Safety
780     ///
781     /// - Appropriate synchronization must be provided for all images
782     ///   that are accessed by the command.
783     /// - All images that are accessed by the command must be in the expected image layout.
784     #[inline]
begin_rendering( &mut self, mut rendering_info: RenderingInfo, ) -> Result<&mut Self, RenderPassError>785     pub unsafe fn begin_rendering(
786         &mut self,
787         mut rendering_info: RenderingInfo,
788     ) -> Result<&mut Self, RenderPassError> {
789         rendering_info.set_extent_layers()?;
790         self.validate_begin_rendering(&rendering_info)?;
791 
792         unsafe { Ok(self.begin_rendering_unchecked(rendering_info)) }
793     }
794 
validate_begin_rendering( &self, rendering_info: &RenderingInfo, ) -> Result<(), RenderPassError>795     fn validate_begin_rendering(
796         &self,
797         rendering_info: &RenderingInfo,
798     ) -> Result<(), RenderPassError> {
799         let device = self.device();
800         let properties = device.physical_device().properties();
801 
802         // VUID-vkCmdBeginRendering-dynamicRendering-06446
803         if !device.enabled_features().dynamic_rendering {
804             return Err(RenderPassError::RequirementNotMet {
805                 required_for: "`CommandBufferBuilder::begin_rendering`",
806                 requires_one_of: RequiresOneOf {
807                     features: &["dynamic_rendering"],
808                     ..Default::default()
809                 },
810             });
811         }
812 
813         let queue_family_properties = self.queue_family_properties();
814 
815         // VUID-vkCmdBeginRendering-commandBuffer-cmdpool
816         if !queue_family_properties
817             .queue_flags
818             .intersects(QueueFlags::GRAPHICS)
819         {
820             return Err(RenderPassError::NotSupportedByQueueFamily);
821         }
822 
823         // VUID-vkCmdBeginRendering-renderpass
824         if self.builder_state.render_pass.is_some() {
825             return Err(RenderPassError::ForbiddenInsideRenderPass);
826         }
827 
828         let &RenderingInfo {
829             render_area_offset,
830             render_area_extent,
831             layer_count,
832             view_mask,
833             ref color_attachments,
834             ref depth_attachment,
835             ref stencil_attachment,
836             contents,
837             _ne: _,
838         } = rendering_info;
839 
840         // VUID-VkRenderingInfo-flags-parameter
841         contents.validate_device(device)?;
842 
843         // VUID-vkCmdBeginRendering-commandBuffer-06068
844         if self.inheritance_info.is_some() && contents == SubpassContents::SecondaryCommandBuffers {
845             return Err(RenderPassError::ContentsForbiddenInSecondaryCommandBuffer);
846         }
847 
848         // No VUID, but for sanity it makes sense to treat this the same as in framebuffers.
849         if view_mask != 0 && layer_count != 1 {
850             return Err(RenderPassError::MultiviewLayersInvalid);
851         }
852 
853         // VUID-VkRenderingInfo-multiview-06127
854         if view_mask != 0 && !device.enabled_features().multiview {
855             return Err(RenderPassError::RequirementNotMet {
856                 required_for: "`rendering_info.viewmask` is not `0`",
857                 requires_one_of: RequiresOneOf {
858                     features: &["multiview"],
859                     ..Default::default()
860                 },
861             });
862         }
863 
864         let view_count = u32::BITS - view_mask.leading_zeros();
865 
866         // VUID-VkRenderingInfo-viewMask-06128
867         if view_count > properties.max_multiview_view_count.unwrap_or(0) {
868             return Err(RenderPassError::MaxMultiviewViewCountExceeded {
869                 view_count,
870                 max: properties.max_multiview_view_count.unwrap_or(0),
871             });
872         }
873 
874         let mut samples = None;
875 
876         // VUID-VkRenderingInfo-colorAttachmentCount-06106
877         if color_attachments.len() > properties.max_color_attachments as usize {
878             return Err(RenderPassError::MaxColorAttachmentsExceeded {
879                 color_attachment_count: color_attachments.len() as u32,
880                 max: properties.max_color_attachments,
881             });
882         }
883 
884         for (attachment_index, attachment_info) in
885             color_attachments
886                 .iter()
887                 .enumerate()
888                 .filter_map(|(index, attachment_info)| {
889                     attachment_info
890                         .as_ref()
891                         .map(|attachment_info| (index, attachment_info))
892                 })
893         {
894             let attachment_index = attachment_index as u32;
895             let RenderingAttachmentInfo {
896                 image_view,
897                 image_layout,
898                 resolve_info,
899                 load_op,
900                 store_op,
901                 clear_value: _,
902                 _ne: _,
903             } = attachment_info;
904 
905             // VUID-VkRenderingAttachmentInfo-imageLayout-parameter
906             image_layout.validate_device(device)?;
907 
908             // VUID-VkRenderingAttachmentInfo-loadOp-parameter
909             load_op.validate_device(device)?;
910 
911             // VUID-VkRenderingAttachmentInfo-storeOp-parameter
912             store_op.validate_device(device)?;
913 
914             // VUID-VkRenderingInfo-colorAttachmentCount-06087
915             if !image_view.usage().intersects(ImageUsage::COLOR_ATTACHMENT) {
916                 return Err(RenderPassError::ColorAttachmentMissingUsage { attachment_index });
917             }
918 
919             let image = image_view.image();
920             let image_extent = image.dimensions().width_height_depth();
921 
922             for i in 0..2 {
923                 // VUID-VkRenderingInfo-pNext-06079
924                 // VUID-VkRenderingInfo-pNext-06080
925                 if render_area_offset[i] + render_area_extent[i] > image_extent[i] {
926                     return Err(RenderPassError::RenderAreaOutOfBounds);
927                 }
928             }
929 
930             // VUID-VkRenderingInfo-imageView-06070
931             match samples {
932                 Some(samples) if samples == image.samples() => (),
933                 Some(_) => {
934                     return Err(RenderPassError::ColorAttachmentSamplesMismatch {
935                         attachment_index,
936                     });
937                 }
938                 None => samples = Some(image.samples()),
939             }
940 
941             // VUID-VkRenderingAttachmentInfo-imageView-06135
942             // VUID-VkRenderingAttachmentInfo-imageView-06145
943             // VUID-VkRenderingInfo-colorAttachmentCount-06090
944             // VUID-VkRenderingInfo-colorAttachmentCount-06096
945             if matches!(
946                 image_layout,
947                 ImageLayout::Undefined
948                     | ImageLayout::ShaderReadOnlyOptimal
949                     | ImageLayout::TransferSrcOptimal
950                     | ImageLayout::TransferDstOptimal
951                     | ImageLayout::Preinitialized
952                     | ImageLayout::PresentSrc
953                     | ImageLayout::DepthStencilAttachmentOptimal
954                     | ImageLayout::DepthStencilReadOnlyOptimal
955                     | ImageLayout::DepthReadOnlyStencilAttachmentOptimal
956                     | ImageLayout::DepthAttachmentStencilReadOnlyOptimal
957             ) {
958                 return Err(RenderPassError::ColorAttachmentLayoutInvalid { attachment_index });
959             }
960 
961             if let Some(resolve_info) = resolve_info {
962                 let &RenderingAttachmentResolveInfo {
963                     mode,
964                     image_view: ref resolve_image_view,
965                     image_layout: resolve_image_layout,
966                 } = resolve_info;
967 
968                 // VUID-VkRenderingAttachmentInfo-resolveImageLayout-parameter
969                 resolve_image_layout.validate_device(device)?;
970 
971                 // VUID-VkRenderingAttachmentInfo-resolveMode-parameter
972                 mode.validate_device(device)?;
973 
974                 let resolve_image = resolve_image_view.image();
975 
976                 match image_view.format().unwrap().type_color() {
977                     Some(
978                         NumericType::SFLOAT
979                         | NumericType::UFLOAT
980                         | NumericType::SNORM
981                         | NumericType::UNORM
982                         | NumericType::SSCALED
983                         | NumericType::USCALED
984                         | NumericType::SRGB,
985                     ) => {
986                         // VUID-VkRenderingAttachmentInfo-imageView-06129
987                         if mode != ResolveMode::Average {
988                             return Err(RenderPassError::ColorAttachmentResolveModeNotSupported {
989                                 attachment_index,
990                             });
991                         }
992                     }
993                     Some(NumericType::SINT | NumericType::UINT) => {
994                         // VUID-VkRenderingAttachmentInfo-imageView-06130
995                         if mode != ResolveMode::SampleZero {
996                             return Err(RenderPassError::ColorAttachmentResolveModeNotSupported {
997                                 attachment_index,
998                             });
999                         }
1000                     }
1001                     None => (),
1002                 }
1003 
1004                 // VUID-VkRenderingAttachmentInfo-imageView-06132
1005                 if image.samples() == SampleCount::Sample1 {
1006                     return Err(RenderPassError::ColorAttachmentWithResolveNotMultisampled {
1007                         attachment_index,
1008                     });
1009                 }
1010 
1011                 // VUID-VkRenderingAttachmentInfo-imageView-06133
1012                 if resolve_image.samples() != SampleCount::Sample1 {
1013                     return Err(RenderPassError::ColorAttachmentResolveMultisampled {
1014                         attachment_index,
1015                     });
1016                 }
1017 
1018                 // VUID-VkRenderingAttachmentInfo-imageView-06134
1019                 if image_view.format() != resolve_image_view.format() {
1020                     return Err(RenderPassError::ColorAttachmentResolveFormatMismatch {
1021                         attachment_index,
1022                     });
1023                 }
1024 
1025                 // VUID-VkRenderingAttachmentInfo-imageView-06136
1026                 // VUID-VkRenderingAttachmentInfo-imageView-06146
1027                 // VUID-VkRenderingInfo-colorAttachmentCount-06091
1028                 // VUID-VkRenderingInfo-colorAttachmentCount-06097
1029                 if matches!(
1030                     resolve_image_layout,
1031                     ImageLayout::Undefined
1032                         | ImageLayout::ShaderReadOnlyOptimal
1033                         | ImageLayout::TransferSrcOptimal
1034                         | ImageLayout::TransferDstOptimal
1035                         | ImageLayout::Preinitialized
1036                         | ImageLayout::PresentSrc
1037                         | ImageLayout::DepthStencilAttachmentOptimal
1038                         | ImageLayout::DepthStencilReadOnlyOptimal
1039                         | ImageLayout::DepthReadOnlyStencilAttachmentOptimal
1040                         | ImageLayout::DepthAttachmentStencilReadOnlyOptimal
1041                 ) {
1042                     return Err(RenderPassError::ColorAttachmentResolveLayoutInvalid {
1043                         attachment_index,
1044                     });
1045                 }
1046             }
1047         }
1048 
1049         if let Some(attachment_info) = depth_attachment {
1050             let RenderingAttachmentInfo {
1051                 image_view,
1052                 image_layout,
1053                 resolve_info,
1054                 load_op,
1055                 store_op,
1056                 clear_value: _,
1057                 _ne: _,
1058             } = attachment_info;
1059 
1060             // VUID-VkRenderingAttachmentInfo-imageLayout-parameter
1061             image_layout.validate_device(device)?;
1062 
1063             // VUID-VkRenderingAttachmentInfo-loadOp-parameter
1064             load_op.validate_device(device)?;
1065 
1066             // VUID-VkRenderingAttachmentInfo-storeOp-parameter
1067             store_op.validate_device(device)?;
1068 
1069             let image_aspects = image_view.format().unwrap().aspects();
1070 
1071             // VUID-VkRenderingInfo-pDepthAttachment-06547
1072             if !image_aspects.intersects(ImageAspects::DEPTH) {
1073                 return Err(RenderPassError::DepthAttachmentFormatUsageNotSupported);
1074             }
1075 
1076             // VUID-VkRenderingInfo-pDepthAttachment-06088
1077             if !image_view
1078                 .usage()
1079                 .intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
1080             {
1081                 return Err(RenderPassError::DepthAttachmentMissingUsage);
1082             }
1083 
1084             let image = image_view.image();
1085             let image_extent = image.dimensions().width_height_depth();
1086 
1087             for i in 0..2 {
1088                 // VUID-VkRenderingInfo-pNext-06079
1089                 // VUID-VkRenderingInfo-pNext-06080
1090                 if render_area_offset[i] + render_area_extent[i] > image_extent[i] {
1091                     return Err(RenderPassError::RenderAreaOutOfBounds);
1092                 }
1093             }
1094 
1095             // VUID-VkRenderingInfo-imageView-06070
1096             match samples {
1097                 Some(samples) if samples == image.samples() => (),
1098                 Some(_) => {
1099                     return Err(RenderPassError::DepthAttachmentSamplesMismatch);
1100                 }
1101                 None => samples = Some(image.samples()),
1102             }
1103 
1104             // VUID-VkRenderingAttachmentInfo-imageView-06135
1105             // VUID-VkRenderingAttachmentInfo-imageView-06145
1106             // VUID-VkRenderingInfo-pDepthAttachment-06092
1107             if matches!(
1108                 image_layout,
1109                 ImageLayout::Undefined
1110                     | ImageLayout::ShaderReadOnlyOptimal
1111                     | ImageLayout::TransferSrcOptimal
1112                     | ImageLayout::TransferDstOptimal
1113                     | ImageLayout::Preinitialized
1114                     | ImageLayout::PresentSrc
1115                     | ImageLayout::ColorAttachmentOptimal
1116             ) {
1117                 return Err(RenderPassError::DepthAttachmentLayoutInvalid);
1118             }
1119 
1120             if let Some(resolve_info) = resolve_info {
1121                 let &RenderingAttachmentResolveInfo {
1122                     mode,
1123                     image_view: ref resolve_image_view,
1124                     image_layout: resolve_image_layout,
1125                 } = resolve_info;
1126 
1127                 // VUID-VkRenderingAttachmentInfo-resolveImageLayout-parameter
1128                 resolve_image_layout.validate_device(device)?;
1129 
1130                 // VUID-VkRenderingAttachmentInfo-resolveMode-parameter
1131                 mode.validate_device(device)?;
1132 
1133                 // VUID-VkRenderingInfo-pDepthAttachment-06102
1134                 if !properties
1135                     .supported_depth_resolve_modes
1136                     .map_or(false, |modes| modes.contains_enum(mode))
1137                 {
1138                     return Err(RenderPassError::DepthAttachmentResolveModeNotSupported);
1139                 }
1140 
1141                 let resolve_image = resolve_image_view.image();
1142 
1143                 // VUID-VkRenderingAttachmentInfo-imageView-06132
1144                 if image.samples() == SampleCount::Sample1 {
1145                     return Err(RenderPassError::DepthAttachmentWithResolveNotMultisampled);
1146                 }
1147 
1148                 // VUID-VkRenderingAttachmentInfo-imageView-06133
1149                 if resolve_image.samples() != SampleCount::Sample1 {
1150                     return Err(RenderPassError::DepthAttachmentResolveMultisampled);
1151                 }
1152 
1153                 // VUID-VkRenderingAttachmentInfo-imageView-06134
1154                 if image_view.format() != resolve_image_view.format() {
1155                     return Err(RenderPassError::DepthAttachmentResolveFormatMismatch);
1156                 }
1157 
1158                 // VUID-VkRenderingAttachmentInfo-imageView-06136
1159                 // VUID-VkRenderingAttachmentInfo-imageView-06146
1160                 // VUID-VkRenderingInfo-pDepthAttachment-06093
1161                 // VUID-VkRenderingInfo-pDepthAttachment-06098
1162                 if matches!(
1163                     resolve_image_layout,
1164                     ImageLayout::Undefined
1165                         | ImageLayout::DepthStencilReadOnlyOptimal
1166                         | ImageLayout::ShaderReadOnlyOptimal
1167                         | ImageLayout::TransferSrcOptimal
1168                         | ImageLayout::TransferDstOptimal
1169                         | ImageLayout::Preinitialized
1170                         | ImageLayout::PresentSrc
1171                         | ImageLayout::ColorAttachmentOptimal
1172                         | ImageLayout::DepthReadOnlyStencilAttachmentOptimal
1173                 ) {
1174                     return Err(RenderPassError::DepthAttachmentResolveLayoutInvalid);
1175                 }
1176             }
1177         }
1178 
1179         if let Some(attachment_info) = stencil_attachment {
1180             let RenderingAttachmentInfo {
1181                 image_view,
1182                 image_layout,
1183                 resolve_info,
1184                 load_op,
1185                 store_op,
1186                 clear_value: _,
1187                 _ne: _,
1188             } = attachment_info;
1189 
1190             // VUID-VkRenderingAttachmentInfo-imageLayout-parameter
1191             image_layout.validate_device(device)?;
1192 
1193             // VUID-VkRenderingAttachmentInfo-loadOp-parameter
1194             load_op.validate_device(device)?;
1195 
1196             // VUID-VkRenderingAttachmentInfo-storeOp-parameter
1197             store_op.validate_device(device)?;
1198 
1199             let image_aspects = image_view.format().unwrap().aspects();
1200 
1201             // VUID-VkRenderingInfo-pStencilAttachment-06548
1202             if !image_aspects.intersects(ImageAspects::STENCIL) {
1203                 return Err(RenderPassError::StencilAttachmentFormatUsageNotSupported);
1204             }
1205 
1206             // VUID-VkRenderingInfo-pStencilAttachment-06089
1207             if !image_view
1208                 .usage()
1209                 .intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
1210             {
1211                 return Err(RenderPassError::StencilAttachmentMissingUsage);
1212             }
1213 
1214             let image = image_view.image();
1215             let image_extent = image.dimensions().width_height_depth();
1216 
1217             for i in 0..2 {
1218                 // VUID-VkRenderingInfo-pNext-06079
1219                 // VUID-VkRenderingInfo-pNext-06080
1220                 if render_area_offset[i] + render_area_extent[i] > image_extent[i] {
1221                     return Err(RenderPassError::RenderAreaOutOfBounds);
1222                 }
1223             }
1224 
1225             // VUID-VkRenderingInfo-imageView-06070
1226             match samples {
1227                 Some(samples) if samples == image.samples() => (),
1228                 Some(_) => {
1229                     return Err(RenderPassError::StencilAttachmentSamplesMismatch);
1230                 }
1231                 None => (),
1232             }
1233 
1234             // VUID-VkRenderingAttachmentInfo-imageView-06135
1235             // VUID-VkRenderingAttachmentInfo-imageView-06145
1236             // VUID-VkRenderingInfo-pStencilAttachment-06094
1237             if matches!(
1238                 image_layout,
1239                 ImageLayout::Undefined
1240                     | ImageLayout::ShaderReadOnlyOptimal
1241                     | ImageLayout::TransferSrcOptimal
1242                     | ImageLayout::TransferDstOptimal
1243                     | ImageLayout::Preinitialized
1244                     | ImageLayout::PresentSrc
1245                     | ImageLayout::ColorAttachmentOptimal
1246             ) {
1247                 return Err(RenderPassError::StencilAttachmentLayoutInvalid);
1248             }
1249 
1250             if let Some(resolve_info) = resolve_info {
1251                 let &RenderingAttachmentResolveInfo {
1252                     mode,
1253                     image_view: ref resolve_image_view,
1254                     image_layout: resolve_image_layout,
1255                 } = resolve_info;
1256 
1257                 // VUID-VkRenderingAttachmentInfo-resolveImageLayout-parameter
1258                 resolve_image_layout.validate_device(device)?;
1259 
1260                 // VUID-VkRenderingAttachmentInfo-resolveMode-parameter
1261                 mode.validate_device(device)?;
1262 
1263                 // VUID-VkRenderingInfo-pStencilAttachment-06103
1264                 if !properties
1265                     .supported_stencil_resolve_modes
1266                     .map_or(false, |modes| modes.contains_enum(mode))
1267                 {
1268                     return Err(RenderPassError::StencilAttachmentResolveModeNotSupported);
1269                 }
1270 
1271                 let resolve_image = resolve_image_view.image();
1272 
1273                 // VUID-VkRenderingAttachmentInfo-imageView-06132
1274                 if image.samples() == SampleCount::Sample1 {
1275                     return Err(RenderPassError::StencilAttachmentWithResolveNotMultisampled);
1276                 }
1277 
1278                 // VUID-VkRenderingAttachmentInfo-imageView-06133
1279                 if resolve_image.samples() != SampleCount::Sample1 {
1280                     return Err(RenderPassError::StencilAttachmentResolveMultisampled);
1281                 }
1282 
1283                 // VUID-VkRenderingAttachmentInfo-imageView-06134
1284                 if image_view.format() != resolve_image_view.format() {
1285                     return Err(RenderPassError::StencilAttachmentResolveFormatMismatch);
1286                 }
1287 
1288                 // VUID-VkRenderingAttachmentInfo-imageView-06136
1289                 // VUID-VkRenderingAttachmentInfo-imageView-06146
1290                 // VUID-VkRenderingInfo-pStencilAttachment-06095
1291                 // VUID-VkRenderingInfo-pStencilAttachment-06099
1292                 if matches!(
1293                     resolve_image_layout,
1294                     ImageLayout::Undefined
1295                         | ImageLayout::DepthStencilReadOnlyOptimal
1296                         | ImageLayout::ShaderReadOnlyOptimal
1297                         | ImageLayout::TransferSrcOptimal
1298                         | ImageLayout::TransferDstOptimal
1299                         | ImageLayout::Preinitialized
1300                         | ImageLayout::PresentSrc
1301                         | ImageLayout::ColorAttachmentOptimal
1302                         | ImageLayout::DepthAttachmentStencilReadOnlyOptimal
1303                 ) {
1304                     return Err(RenderPassError::StencilAttachmentResolveLayoutInvalid);
1305                 }
1306             }
1307         }
1308 
1309         if let (Some(depth_attachment_info), Some(stencil_attachment_info)) =
1310             (depth_attachment, stencil_attachment)
1311         {
1312             // VUID-VkRenderingInfo-pDepthAttachment-06085
1313             if &depth_attachment_info.image_view != &stencil_attachment_info.image_view {
1314                 return Err(RenderPassError::DepthStencilAttachmentImageViewMismatch);
1315             }
1316 
1317             match (
1318                 &depth_attachment_info.resolve_info,
1319                 &stencil_attachment_info.resolve_info,
1320             ) {
1321                 (None, None) => (),
1322                 (None, Some(_)) | (Some(_), None) => {
1323                     // VUID-VkRenderingInfo-pDepthAttachment-06104
1324                     if !properties.independent_resolve_none.unwrap_or(false) {
1325                         return Err(
1326                             RenderPassError::DepthStencilAttachmentResolveModesNotSupported,
1327                         );
1328                     }
1329                 }
1330                 (Some(depth_resolve_info), Some(stencil_resolve_info)) => {
1331                     // VUID-VkRenderingInfo-pDepthAttachment-06105
1332                     if !properties.independent_resolve.unwrap_or(false)
1333                         && depth_resolve_info.mode != stencil_resolve_info.mode
1334                     {
1335                         return Err(
1336                             RenderPassError::DepthStencilAttachmentResolveModesNotSupported,
1337                         );
1338                     }
1339 
1340                     // VUID-VkRenderingInfo-pDepthAttachment-06086
1341                     if &depth_resolve_info.image_view != &stencil_resolve_info.image_view {
1342                         return Err(
1343                             RenderPassError::DepthStencilAttachmentResolveImageViewMismatch,
1344                         );
1345                     }
1346                 }
1347             }
1348         }
1349 
1350         // TODO: sync check
1351 
1352         Ok(())
1353     }
1354 
1355     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
begin_rendering_unchecked(&mut self, rendering_info: RenderingInfo) -> &mut Self1356     pub unsafe fn begin_rendering_unchecked(&mut self, rendering_info: RenderingInfo) -> &mut Self {
1357         {
1358             let &RenderingInfo {
1359                 render_area_offset,
1360                 render_area_extent,
1361                 layer_count,
1362                 view_mask,
1363                 ref color_attachments,
1364                 ref depth_attachment,
1365                 ref stencil_attachment,
1366                 contents,
1367                 _ne,
1368             } = &rendering_info;
1369 
1370             let map_attachment_info = |attachment_info: &Option<_>| {
1371                 if let Some(attachment_info) = attachment_info {
1372                     let &RenderingAttachmentInfo {
1373                         ref image_view,
1374                         image_layout,
1375                         resolve_info: ref resolve,
1376                         load_op,
1377                         store_op,
1378                         clear_value,
1379                         _ne: _,
1380                     } = attachment_info;
1381 
1382                     let (resolve_mode, resolve_image_view, resolve_image_layout) =
1383                         if let Some(resolve) = resolve {
1384                             let &RenderingAttachmentResolveInfo {
1385                                 mode,
1386                                 ref image_view,
1387                                 image_layout,
1388                             } = resolve;
1389 
1390                             (mode.into(), image_view.handle(), image_layout.into())
1391                         } else {
1392                             (
1393                                 ash::vk::ResolveModeFlags::NONE,
1394                                 Default::default(),
1395                                 Default::default(),
1396                             )
1397                         };
1398 
1399                     ash::vk::RenderingAttachmentInfo {
1400                         image_view: image_view.handle(),
1401                         image_layout: image_layout.into(),
1402                         resolve_mode,
1403                         resolve_image_view,
1404                         resolve_image_layout,
1405                         load_op: load_op.into(),
1406                         store_op: store_op.into(),
1407                         clear_value: clear_value.map_or_else(Default::default, Into::into),
1408                         ..Default::default()
1409                     }
1410                 } else {
1411                     ash::vk::RenderingAttachmentInfo {
1412                         image_view: ash::vk::ImageView::null(),
1413                         ..Default::default()
1414                     }
1415                 }
1416             };
1417 
1418             let color_attachments_vk: SmallVec<[_; 2]> =
1419                 color_attachments.iter().map(map_attachment_info).collect();
1420             let depth_attachment_vk = map_attachment_info(depth_attachment);
1421             let stencil_attachment_vk = map_attachment_info(stencil_attachment);
1422 
1423             let rendering_info_vk = ash::vk::RenderingInfo {
1424                 flags: contents.into(),
1425                 render_area: ash::vk::Rect2D {
1426                     offset: ash::vk::Offset2D {
1427                         x: render_area_offset[0] as i32,
1428                         y: render_area_offset[1] as i32,
1429                     },
1430                     extent: ash::vk::Extent2D {
1431                         width: render_area_extent[0],
1432                         height: render_area_extent[1],
1433                     },
1434                 },
1435                 layer_count,
1436                 view_mask,
1437                 color_attachment_count: color_attachments_vk.len() as u32,
1438                 p_color_attachments: color_attachments_vk.as_ptr(),
1439                 p_depth_attachment: &depth_attachment_vk,
1440                 p_stencil_attachment: &stencil_attachment_vk,
1441                 ..Default::default()
1442             };
1443 
1444             let fns = self.device().fns();
1445 
1446             if self.device().api_version() >= Version::V1_3 {
1447                 (fns.v1_3.cmd_begin_rendering)(self.handle(), &rendering_info_vk);
1448             } else {
1449                 debug_assert!(self.device().enabled_extensions().khr_dynamic_rendering);
1450                 (fns.khr_dynamic_rendering.cmd_begin_rendering_khr)(
1451                     self.handle(),
1452                     &rendering_info_vk,
1453                 );
1454             }
1455 
1456             self.builder_state.render_pass = Some(RenderPassState {
1457                 contents,
1458                 render_area_offset,
1459                 render_area_extent,
1460 
1461                 rendering_info: PipelineRenderingCreateInfo::from_rendering_info(&rendering_info),
1462                 attachments: Some(RenderPassStateAttachments::from_rendering_info(
1463                     &rendering_info,
1464                 )),
1465 
1466                 render_pass: BeginRenderingState {
1467                     pipeline_used: false,
1468                 }
1469                 .into(),
1470             });
1471         }
1472 
1473         let RenderingInfo {
1474             color_attachments,
1475             depth_attachment,
1476             stencil_attachment,
1477             ..
1478         } = rendering_info;
1479 
1480         for attachment_info in color_attachments.into_iter().flatten() {
1481             let RenderingAttachmentInfo {
1482                 image_view,
1483                 image_layout: _,
1484                 resolve_info,
1485                 load_op: _,
1486                 store_op: _,
1487                 clear_value: _,
1488                 _ne: _,
1489             } = attachment_info;
1490 
1491             self.resources.push(Box::new(image_view));
1492 
1493             if let Some(resolve_info) = resolve_info {
1494                 let RenderingAttachmentResolveInfo {
1495                     mode: _,
1496                     image_view,
1497                     image_layout: _,
1498                 } = resolve_info;
1499 
1500                 self.resources.push(Box::new(image_view));
1501             }
1502         }
1503 
1504         if let Some(attachment_info) = depth_attachment {
1505             let RenderingAttachmentInfo {
1506                 image_view,
1507                 image_layout: _,
1508                 resolve_info,
1509                 load_op: _,
1510                 store_op: _,
1511                 clear_value: _,
1512                 _ne: _,
1513             } = attachment_info;
1514 
1515             self.resources.push(Box::new(image_view));
1516 
1517             if let Some(resolve_info) = resolve_info {
1518                 let RenderingAttachmentResolveInfo {
1519                     mode: _,
1520                     image_view,
1521                     image_layout: _,
1522                 } = resolve_info;
1523 
1524                 self.resources.push(Box::new(image_view));
1525             }
1526         }
1527 
1528         if let Some(attachment_info) = stencil_attachment {
1529             let RenderingAttachmentInfo {
1530                 image_view,
1531                 image_layout: _,
1532                 resolve_info,
1533                 load_op: _,
1534                 store_op: _,
1535                 clear_value: _,
1536                 _ne: _,
1537             } = attachment_info;
1538 
1539             self.resources.push(Box::new(image_view));
1540 
1541             if let Some(resolve_info) = resolve_info {
1542                 let RenderingAttachmentResolveInfo {
1543                     mode: _,
1544                     image_view,
1545                     image_layout: _,
1546                 } = resolve_info;
1547 
1548                 self.resources.push(Box::new(image_view));
1549             }
1550         }
1551 
1552         self.next_command_index += 1;
1553         self
1554     }
1555 
1556     /// Ends the render pass previously begun with `begin_rendering`.
1557     ///
1558     /// # Safety
1559     ///
1560     /// - Appropriate synchronization must be provided for all images
1561     ///   that are accessed by the command.
1562     /// - All images that are accessed by the command must be in the expected image layout.
1563     #[inline]
end_rendering(&mut self) -> Result<&mut Self, RenderPassError>1564     pub unsafe fn end_rendering(&mut self) -> Result<&mut Self, RenderPassError> {
1565         self.validate_end_rendering()?;
1566 
1567         unsafe { Ok(self.end_rendering_unchecked()) }
1568     }
1569 
validate_end_rendering(&self) -> Result<(), RenderPassError>1570     fn validate_end_rendering(&self) -> Result<(), RenderPassError> {
1571         // VUID-vkCmdEndRendering-renderpass
1572         let render_pass_state = self
1573             .builder_state
1574             .render_pass
1575             .as_ref()
1576             .ok_or(RenderPassError::ForbiddenOutsideRenderPass)?;
1577 
1578         // VUID?
1579         if self.inheritance_info.is_some() {
1580             return Err(RenderPassError::ForbiddenWithInheritedRenderPass);
1581         }
1582 
1583         // VUID-vkCmdEndRendering-None-06161
1584         // VUID-vkCmdEndRendering-commandBuffer-06162
1585         match &render_pass_state.render_pass {
1586             RenderPassStateType::BeginRenderPass(_) => {
1587                 return Err(RenderPassError::ForbiddenWithBeginRenderPass)
1588             }
1589             RenderPassStateType::BeginRendering(_) => (),
1590         }
1591 
1592         // VUID-vkCmdEndRendering-commandBuffer-cmdpool
1593         debug_assert!(self
1594             .queue_family_properties()
1595             .queue_flags
1596             .intersects(QueueFlags::GRAPHICS));
1597 
1598         // TODO: sync check
1599 
1600         Ok(())
1601     }
1602 
1603     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
end_rendering_unchecked(&mut self) -> &mut Self1604     pub unsafe fn end_rendering_unchecked(&mut self) -> &mut Self {
1605         let fns = self.device().fns();
1606 
1607         if self.device().api_version() >= Version::V1_3 {
1608             (fns.v1_3.cmd_end_rendering)(self.handle());
1609         } else {
1610             debug_assert!(self.device().enabled_extensions().khr_dynamic_rendering);
1611             (fns.khr_dynamic_rendering.cmd_end_rendering_khr)(self.handle());
1612         }
1613 
1614         let command_index = self.next_command_index;
1615         let command_name = "end_rendering";
1616         let render_pass_state = self.builder_state.render_pass.as_ref().unwrap();
1617 
1618         record_subpass_attachments_resolve(
1619             &mut self.resources_usage_state,
1620             command_index,
1621             command_name,
1622             render_pass_state,
1623         );
1624         record_subpass_attachments_store(
1625             &mut self.resources_usage_state,
1626             command_index,
1627             command_name,
1628             render_pass_state,
1629         );
1630 
1631         self.builder_state.render_pass = None;
1632 
1633         self.next_command_index += 1;
1634         self
1635     }
1636 
1637     /// Clears specific regions of specific attachments of the framebuffer.
1638     ///
1639     /// `attachments` specify the types of attachments and their clear values.
1640     /// `rects` specify the regions to clear.
1641     ///
1642     /// A graphics pipeline must have been bound using [`bind_pipeline_graphics`].
1643     /// And the command must be inside render pass.
1644     ///
1645     /// If the render pass instance this is recorded in uses multiview,
1646     /// then `ClearRect.base_array_layer` must be zero and `ClearRect.layer_count` must be one.
1647     ///
1648     /// The rectangle area must be inside the render area ranges.
1649     ///
1650     /// # Safety
1651     ///
1652     /// - Appropriate synchronization must be provided for all images
1653     ///   that are accessed by the command.
1654     /// - All images that are accessed by the command must be in the expected image layout.
1655     ///
1656     /// [`bind_pipeline_graphics`]: Self::bind_pipeline_graphics
1657     #[inline]
clear_attachments( &mut self, attachments: impl IntoIterator<Item = ClearAttachment>, rects: impl IntoIterator<Item = ClearRect>, ) -> Result<&mut Self, RenderPassError>1658     pub unsafe fn clear_attachments(
1659         &mut self,
1660         attachments: impl IntoIterator<Item = ClearAttachment>,
1661         rects: impl IntoIterator<Item = ClearRect>,
1662     ) -> Result<&mut Self, RenderPassError> {
1663         let attachments: SmallVec<[ClearAttachment; 3]> = attachments.into_iter().collect();
1664         let rects: SmallVec<[ClearRect; 4]> = rects.into_iter().collect();
1665 
1666         self.validate_clear_attachments(&attachments, &rects)?;
1667 
1668         unsafe { Ok(self.clear_attachments_unchecked(attachments, rects)) }
1669     }
1670 
validate_clear_attachments( &self, attachments: &[ClearAttachment], rects: &[ClearRect], ) -> Result<(), RenderPassError>1671     fn validate_clear_attachments(
1672         &self,
1673         attachments: &[ClearAttachment],
1674         rects: &[ClearRect],
1675     ) -> Result<(), RenderPassError> {
1676         // VUID-vkCmdClearAttachments-renderpass
1677         let render_pass_state = self
1678             .builder_state
1679             .render_pass
1680             .as_ref()
1681             .ok_or(RenderPassError::ForbiddenOutsideRenderPass)?;
1682 
1683         if render_pass_state.contents != SubpassContents::Inline {
1684             return Err(RenderPassError::ForbiddenWithSubpassContents {
1685                 contents: render_pass_state.contents,
1686             });
1687         }
1688 
1689         //let subpass_desc = begin_render_pass_state.subpass.subpass_desc();
1690         //let render_pass = begin_render_pass_state.subpass.render_pass();
1691         let is_multiview = render_pass_state.rendering_info.view_mask != 0;
1692         let mut layer_count = u32::MAX;
1693 
1694         for &clear_attachment in attachments {
1695             match clear_attachment {
1696                 ClearAttachment::Color {
1697                     color_attachment,
1698                     clear_value,
1699                 } => {
1700                     let attachment_format = *render_pass_state
1701                         .rendering_info
1702                         .color_attachment_formats
1703                         .get(color_attachment as usize)
1704                         .ok_or(RenderPassError::ColorAttachmentIndexOutOfRange {
1705                             color_attachment_index: color_attachment,
1706                             num_color_attachments: render_pass_state
1707                                 .rendering_info
1708                                 .color_attachment_formats
1709                                 .len() as u32,
1710                         })?;
1711 
1712                     // VUID-vkCmdClearAttachments-aspectMask-02501
1713                     if !attachment_format.map_or(false, |format| {
1714                         matches!(
1715                             (clear_value, format.type_color().unwrap()),
1716                             (
1717                                 ClearColorValue::Float(_),
1718                                 NumericType::SFLOAT
1719                                     | NumericType::UFLOAT
1720                                     | NumericType::SNORM
1721                                     | NumericType::UNORM
1722                                     | NumericType::SSCALED
1723                                     | NumericType::USCALED
1724                                     | NumericType::SRGB
1725                             ) | (ClearColorValue::Int(_), NumericType::SINT)
1726                                 | (ClearColorValue::Uint(_), NumericType::UINT)
1727                         )
1728                     }) {
1729                         return Err(RenderPassError::ClearAttachmentNotCompatible {
1730                             clear_attachment,
1731                             attachment_format,
1732                         });
1733                     }
1734 
1735                     let image_view = render_pass_state
1736                         .attachments
1737                         .as_ref()
1738                         .and_then(|attachments| {
1739                             attachments.color_attachments[color_attachment as usize].as_ref()
1740                         })
1741                         .map(|attachment_info| &attachment_info.image_view);
1742 
1743                     // We only know the layer count if we have a known attachment image.
1744                     if let Some(image_view) = image_view {
1745                         let array_layers = &image_view.subresource_range().array_layers;
1746                         layer_count = min(layer_count, array_layers.end - array_layers.start);
1747                     }
1748                 }
1749                 ClearAttachment::Depth(_)
1750                 | ClearAttachment::Stencil(_)
1751                 | ClearAttachment::DepthStencil(_) => {
1752                     let depth_format = render_pass_state.rendering_info.depth_attachment_format;
1753                     let stencil_format = render_pass_state.rendering_info.stencil_attachment_format;
1754 
1755                     // VUID-vkCmdClearAttachments-aspectMask-02502
1756                     if matches!(
1757                         clear_attachment,
1758                         ClearAttachment::Depth(_) | ClearAttachment::DepthStencil(_)
1759                     ) && !depth_format.map_or(false, |format| {
1760                         format.aspects().intersects(ImageAspects::DEPTH)
1761                     }) {
1762                         return Err(RenderPassError::ClearAttachmentNotCompatible {
1763                             clear_attachment,
1764                             attachment_format: None,
1765                         });
1766                     }
1767 
1768                     // VUID-vkCmdClearAttachments-aspectMask-02503
1769                     if matches!(
1770                         clear_attachment,
1771                         ClearAttachment::Stencil(_) | ClearAttachment::DepthStencil(_)
1772                     ) && !stencil_format.map_or(false, |format| {
1773                         format.aspects().intersects(ImageAspects::STENCIL)
1774                     }) {
1775                         return Err(RenderPassError::ClearAttachmentNotCompatible {
1776                             clear_attachment,
1777                             attachment_format: None,
1778                         });
1779                     }
1780 
1781                     let image_view = render_pass_state
1782                         .attachments
1783                         .as_ref()
1784                         .and_then(|attachments| attachments.depth_attachment.as_ref())
1785                         .map(|attachment_info| &attachment_info.image_view);
1786 
1787                     // We only know the layer count if we have a known attachment image.
1788                     if let Some(image_view) = image_view {
1789                         let array_layers = &image_view.subresource_range().array_layers;
1790                         layer_count = min(layer_count, array_layers.end - array_layers.start);
1791                     }
1792                 }
1793             }
1794         }
1795 
1796         for (rect_index, rect) in rects.iter().enumerate() {
1797             for i in 0..2 {
1798                 // VUID-vkCmdClearAttachments-rect-02682
1799                 // VUID-vkCmdClearAttachments-rect-02683
1800                 if rect.extent[i] == 0 {
1801                     return Err(RenderPassError::RectExtentZero { rect_index });
1802                 }
1803 
1804                 // VUID-vkCmdClearAttachments-pRects-00016
1805                 // TODO: This check will always pass in secondary command buffers because of how
1806                 // it's set in `with_level`.
1807                 // It needs to be checked during `execute_commands` instead.
1808                 if rect.offset[i] < render_pass_state.render_area_offset[i]
1809                     || rect.offset[i] + rect.extent[i]
1810                         > render_pass_state.render_area_offset[i]
1811                             + render_pass_state.render_area_extent[i]
1812                 {
1813                     return Err(RenderPassError::RectOutOfBounds { rect_index });
1814                 }
1815             }
1816 
1817             // VUID-vkCmdClearAttachments-layerCount-01934
1818             if rect.array_layers.is_empty() {
1819                 return Err(RenderPassError::RectArrayLayersEmpty { rect_index });
1820             }
1821 
1822             // VUID-vkCmdClearAttachments-pRects-00017
1823             if rect.array_layers.end > layer_count {
1824                 return Err(RenderPassError::RectArrayLayersOutOfBounds { rect_index });
1825             }
1826 
1827             // VUID-vkCmdClearAttachments-baseArrayLayer-00018
1828             if is_multiview && rect.array_layers != (0..1) {
1829                 return Err(RenderPassError::MultiviewRectArrayLayersInvalid { rect_index });
1830             }
1831         }
1832 
1833         // VUID-vkCmdClearAttachments-commandBuffer-cmdpool
1834         debug_assert!(self
1835             .queue_family_properties()
1836             .queue_flags
1837             .intersects(QueueFlags::GRAPHICS));
1838 
1839         // TODO: sync check
1840 
1841         Ok(())
1842     }
1843 
1844     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
clear_attachments_unchecked( &mut self, attachments: impl IntoIterator<Item = ClearAttachment>, rects: impl IntoIterator<Item = ClearRect>, ) -> &mut Self1845     pub unsafe fn clear_attachments_unchecked(
1846         &mut self,
1847         attachments: impl IntoIterator<Item = ClearAttachment>,
1848         rects: impl IntoIterator<Item = ClearRect>,
1849     ) -> &mut Self {
1850         let attachments_vk: SmallVec<[_; 3]> = attachments.into_iter().map(|v| v.into()).collect();
1851         let rects_vk: SmallVec<[_; 4]> = rects
1852             .into_iter()
1853             .map(|rect| ash::vk::ClearRect {
1854                 rect: ash::vk::Rect2D {
1855                     offset: ash::vk::Offset2D {
1856                         x: rect.offset[0] as i32,
1857                         y: rect.offset[1] as i32,
1858                     },
1859                     extent: ash::vk::Extent2D {
1860                         width: rect.extent[0],
1861                         height: rect.extent[1],
1862                     },
1863                 },
1864                 base_array_layer: rect.array_layers.start,
1865                 layer_count: rect.array_layers.end - rect.array_layers.start,
1866             })
1867             .collect();
1868 
1869         if attachments_vk.is_empty() || rects_vk.is_empty() {
1870             return self;
1871         }
1872 
1873         let fns = self.device().fns();
1874         (fns.v1_0.cmd_clear_attachments)(
1875             self.handle(),
1876             attachments_vk.len() as u32,
1877             attachments_vk.as_ptr(),
1878             rects_vk.len() as u32,
1879             rects_vk.as_ptr(),
1880         );
1881 
1882         // TODO: sync state update
1883 
1884         self.next_command_index += 1;
1885         self
1886     }
1887 }
1888 
record_subpass_attachments_resolve( resources_usage_state: &mut ResourcesState, command_index: usize, command_name: &'static str, render_pass_state: &RenderPassState, )1889 fn record_subpass_attachments_resolve(
1890     resources_usage_state: &mut ResourcesState,
1891     command_index: usize,
1892     command_name: &'static str,
1893     render_pass_state: &RenderPassState,
1894 ) {
1895     let attachments = render_pass_state.attachments.as_ref().unwrap();
1896 
1897     let record_attachment = |resources_usage_state: &mut ResourcesState,
1898                              attachment_info,
1899                              aspects_override,
1900                              resource_in_command,
1901                              resolve_resource_in_command| {
1902         let &RenderPassStateAttachmentInfo {
1903             ref image_view,
1904             image_layout,
1905             ref resolve_info,
1906             ..
1907         } = attachment_info;
1908 
1909         let image = image_view.image();
1910         let image_inner = image.inner();
1911         let mut subresource_range = image_view.subresource_range().clone();
1912         subresource_range.array_layers.start += image_inner.first_layer;
1913         subresource_range.array_layers.end += image_inner.first_layer;
1914         subresource_range.mip_levels.start += image_inner.first_mipmap_level;
1915         subresource_range.mip_levels.end += image_inner.first_mipmap_level;
1916 
1917         if let Some(aspects) = aspects_override {
1918             subresource_range.aspects = aspects;
1919         }
1920 
1921         let use_ref = ResourceUseRef {
1922             command_index,
1923             command_name,
1924             resource_in_command,
1925             secondary_use_ref: None,
1926         };
1927 
1928         if let Some(resolve_info) = resolve_info {
1929             let &RenderPassStateAttachmentResolveInfo {
1930                 image_view: ref resolve_image_view,
1931                 image_layout: resolve_image_layout,
1932                 ..
1933             } = resolve_info;
1934 
1935             let resolve_image = resolve_image_view.image();
1936             let resolve_image_inner = resolve_image.inner();
1937             let mut resolve_subresource_range = resolve_image_view.subresource_range().clone();
1938             resolve_subresource_range.array_layers.start += resolve_image_inner.first_layer;
1939             resolve_subresource_range.array_layers.end += resolve_image_inner.first_layer;
1940             resolve_subresource_range.mip_levels.start += resolve_image_inner.first_mipmap_level;
1941             resolve_subresource_range.mip_levels.end += resolve_image_inner.first_mipmap_level;
1942 
1943             if let Some(aspects) = aspects_override {
1944                 resolve_subresource_range.aspects = aspects;
1945             }
1946 
1947             let resolve_use_ref = ResourceUseRef {
1948                 command_index,
1949                 command_name,
1950                 resource_in_command: resolve_resource_in_command,
1951                 secondary_use_ref: None,
1952             };
1953 
1954             // The resolve operation uses the stages/access for color attachments,
1955             // even for depth/stencil attachments.
1956             resources_usage_state.record_image_access(
1957                 &use_ref,
1958                 image_inner.image,
1959                 subresource_range,
1960                 PipelineStageAccess::ColorAttachmentOutput_ColorAttachmentRead,
1961                 image_layout,
1962             );
1963             resources_usage_state.record_image_access(
1964                 &resolve_use_ref,
1965                 resolve_image_inner.image,
1966                 resolve_subresource_range,
1967                 PipelineStageAccess::ColorAttachmentOutput_ColorAttachmentWrite,
1968                 resolve_image_layout,
1969             );
1970         }
1971     };
1972 
1973     if let Some(attachment_info) = attachments.depth_attachment.as_ref() {
1974         record_attachment(
1975             resources_usage_state,
1976             attachment_info,
1977             Some(ImageAspects::DEPTH),
1978             ResourceInCommand::DepthStencilAttachment,
1979             ResourceInCommand::DepthStencilResolveAttachment,
1980         );
1981     }
1982 
1983     if let Some(attachment_info) = attachments.stencil_attachment.as_ref() {
1984         record_attachment(
1985             resources_usage_state,
1986             attachment_info,
1987             Some(ImageAspects::STENCIL),
1988             ResourceInCommand::DepthStencilAttachment,
1989             ResourceInCommand::DepthStencilResolveAttachment,
1990         );
1991     }
1992 
1993     for (index, attachment_info) in (attachments.color_attachments.iter().enumerate())
1994         .filter_map(|(i, a)| a.as_ref().map(|a| (i as u32, a)))
1995     {
1996         record_attachment(
1997             resources_usage_state,
1998             attachment_info,
1999             None,
2000             ResourceInCommand::ColorAttachment { index },
2001             ResourceInCommand::ColorResolveAttachment { index },
2002         );
2003     }
2004 }
2005 
record_subpass_attachments_store( resources_usage_state: &mut ResourcesState, command_index: usize, command_name: &'static str, render_pass_state: &RenderPassState, )2006 fn record_subpass_attachments_store(
2007     resources_usage_state: &mut ResourcesState,
2008     command_index: usize,
2009     command_name: &'static str,
2010     render_pass_state: &RenderPassState,
2011 ) {
2012     let attachments = render_pass_state.attachments.as_ref().unwrap();
2013 
2014     let record_attachment = |resources_usage_state: &mut ResourcesState,
2015                              attachment_info,
2016                              aspects_override,
2017                              resource_in_command,
2018                              resolve_resource_in_command| {
2019         let &RenderPassStateAttachmentInfo {
2020             ref image_view,
2021             image_layout,
2022             store_access,
2023             ref resolve_info,
2024             ..
2025         } = attachment_info;
2026 
2027         if let Some(access) = store_access {
2028             let image = image_view.image();
2029             let image_inner = image.inner();
2030             let mut subresource_range = image_view.subresource_range().clone();
2031             subresource_range.array_layers.start += image_inner.first_layer;
2032             subresource_range.array_layers.end += image_inner.first_layer;
2033             subresource_range.mip_levels.start += image_inner.first_mipmap_level;
2034             subresource_range.mip_levels.end += image_inner.first_mipmap_level;
2035 
2036             if let Some(aspects) = aspects_override {
2037                 subresource_range.aspects = aspects;
2038             }
2039 
2040             let use_ref = ResourceUseRef {
2041                 command_index,
2042                 command_name,
2043                 resource_in_command,
2044                 secondary_use_ref: None,
2045             };
2046 
2047             resources_usage_state.record_image_access(
2048                 &use_ref,
2049                 image_inner.image,
2050                 subresource_range,
2051                 access,
2052                 image_layout,
2053             );
2054         }
2055 
2056         if let Some(resolve_info) = resolve_info {
2057             let &RenderPassStateAttachmentResolveInfo {
2058                 ref image_view,
2059                 image_layout,
2060                 store_access,
2061                 ..
2062             } = resolve_info;
2063 
2064             if let Some(access) = store_access {
2065                 let image = image_view.image();
2066                 let image_inner = image.inner();
2067                 let mut subresource_range = image_view.subresource_range().clone();
2068                 subresource_range.array_layers.start += image_inner.first_layer;
2069                 subresource_range.array_layers.end += image_inner.first_layer;
2070                 subresource_range.mip_levels.start += image_inner.first_mipmap_level;
2071                 subresource_range.mip_levels.end += image_inner.first_mipmap_level;
2072 
2073                 if let Some(aspects) = aspects_override {
2074                     subresource_range.aspects = aspects;
2075                 }
2076 
2077                 let use_ref = ResourceUseRef {
2078                     command_index,
2079                     command_name,
2080                     resource_in_command: resolve_resource_in_command,
2081                     secondary_use_ref: None,
2082                 };
2083 
2084                 resources_usage_state.record_image_access(
2085                     &use_ref,
2086                     image_inner.image,
2087                     subresource_range,
2088                     access,
2089                     image_layout,
2090                 );
2091             }
2092         }
2093     };
2094 
2095     if let Some(attachment_info) = attachments.depth_attachment.as_ref() {
2096         record_attachment(
2097             resources_usage_state,
2098             attachment_info,
2099             Some(ImageAspects::DEPTH),
2100             ResourceInCommand::DepthStencilAttachment,
2101             ResourceInCommand::DepthStencilResolveAttachment,
2102         );
2103     }
2104 
2105     if let Some(attachment_info) = attachments.stencil_attachment.as_ref() {
2106         record_attachment(
2107             resources_usage_state,
2108             attachment_info,
2109             Some(ImageAspects::STENCIL),
2110             ResourceInCommand::DepthStencilAttachment,
2111             ResourceInCommand::DepthStencilResolveAttachment,
2112         );
2113     }
2114 
2115     for (index, attachment_info) in (attachments.color_attachments.iter().enumerate())
2116         .filter_map(|(i, a)| a.as_ref().map(|a| (i as u32, a)))
2117     {
2118         record_attachment(
2119             resources_usage_state,
2120             attachment_info,
2121             None,
2122             ResourceInCommand::ColorAttachment { index },
2123             ResourceInCommand::ColorResolveAttachment { index },
2124         );
2125     }
2126 }
2127 
record_subpass_attachments_load( resources_usage_state: &mut ResourcesState, command_index: usize, command_name: &'static str, render_pass_state: &RenderPassState, )2128 fn record_subpass_attachments_load(
2129     resources_usage_state: &mut ResourcesState,
2130     command_index: usize,
2131     command_name: &'static str,
2132     render_pass_state: &RenderPassState,
2133 ) {
2134     let attachments = render_pass_state.attachments.as_ref().unwrap();
2135 
2136     let record_attachment = |resources_usage_state: &mut ResourcesState,
2137                              attachment_info,
2138                              aspects_override,
2139                              resource_in_command,
2140                              resolve_resource_in_command| {
2141         let &RenderPassStateAttachmentInfo {
2142             ref image_view,
2143             image_layout,
2144             load_access,
2145             ref resolve_info,
2146             ..
2147         } = attachment_info;
2148 
2149         if let Some(access) = load_access {
2150             let image = image_view.image();
2151             let image_inner = image.inner();
2152             let mut subresource_range = image_view.subresource_range().clone();
2153             subresource_range.array_layers.start += image_inner.first_layer;
2154             subresource_range.array_layers.end += image_inner.first_layer;
2155             subresource_range.mip_levels.start += image_inner.first_mipmap_level;
2156             subresource_range.mip_levels.end += image_inner.first_mipmap_level;
2157 
2158             if let Some(aspects) = aspects_override {
2159                 subresource_range.aspects = aspects;
2160             }
2161 
2162             let use_ref = ResourceUseRef {
2163                 command_index,
2164                 command_name,
2165                 resource_in_command,
2166                 secondary_use_ref: None,
2167             };
2168 
2169             resources_usage_state.record_image_access(
2170                 &use_ref,
2171                 image_inner.image,
2172                 subresource_range,
2173                 access,
2174                 image_layout,
2175             );
2176         }
2177 
2178         if let Some(resolve_info) = resolve_info {
2179             let &RenderPassStateAttachmentResolveInfo {
2180                 ref image_view,
2181                 image_layout,
2182                 load_access,
2183                 ..
2184             } = resolve_info;
2185 
2186             if let Some(access) = load_access {
2187                 let image = image_view.image();
2188                 let image_inner = image.inner();
2189                 let mut subresource_range = image_view.subresource_range().clone();
2190                 subresource_range.array_layers.start += image_inner.first_layer;
2191                 subresource_range.array_layers.end += image_inner.first_layer;
2192                 subresource_range.mip_levels.start += image_inner.first_mipmap_level;
2193                 subresource_range.mip_levels.end += image_inner.first_mipmap_level;
2194 
2195                 if let Some(aspects) = aspects_override {
2196                     subresource_range.aspects = aspects;
2197                 }
2198 
2199                 let use_ref = ResourceUseRef {
2200                     command_index,
2201                     command_name,
2202                     resource_in_command: resolve_resource_in_command,
2203                     secondary_use_ref: None,
2204                 };
2205 
2206                 resources_usage_state.record_image_access(
2207                     &use_ref,
2208                     image_inner.image,
2209                     subresource_range,
2210                     access,
2211                     image_layout,
2212                 );
2213             }
2214         }
2215     };
2216 
2217     if let Some(attachment_info) = attachments.depth_attachment.as_ref() {
2218         record_attachment(
2219             resources_usage_state,
2220             attachment_info,
2221             Some(ImageAspects::DEPTH),
2222             ResourceInCommand::DepthStencilAttachment,
2223             ResourceInCommand::DepthStencilResolveAttachment,
2224         );
2225     }
2226 
2227     if let Some(attachment_info) = attachments.stencil_attachment.as_ref() {
2228         record_attachment(
2229             resources_usage_state,
2230             attachment_info,
2231             Some(ImageAspects::STENCIL),
2232             ResourceInCommand::DepthStencilAttachment,
2233             ResourceInCommand::DepthStencilResolveAttachment,
2234         );
2235     }
2236 
2237     for (index, attachment_info) in (attachments.color_attachments.iter().enumerate())
2238         .filter_map(|(i, a)| a.as_ref().map(|a| (i as u32, a)))
2239     {
2240         record_attachment(
2241             resources_usage_state,
2242             attachment_info,
2243             None,
2244             ResourceInCommand::ColorAttachment { index },
2245             ResourceInCommand::ColorResolveAttachment { index },
2246         );
2247     }
2248 }
2249