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     AttachmentDescription, AttachmentReference, LoadOp, RenderPass, RenderPassCreateInfo,
12     SubpassDependency, SubpassDescription,
13 };
14 use crate::{
15     device::Device,
16     format::FormatFeatures,
17     image::{ImageAspects, ImageLayout, SampleCount},
18     sync::{AccessFlags, DependencyFlags, PipelineStages},
19     OomError, RequirementNotMet, RequiresOneOf, Version, VulkanError, VulkanObject,
20 };
21 use smallvec::SmallVec;
22 use std::{
23     error::Error,
24     fmt::{Display, Error as FmtError, Formatter},
25     mem::MaybeUninit,
26     ptr,
27 };
28 
29 impl RenderPass {
validate( device: &Device, create_info: &mut RenderPassCreateInfo, ) -> Result<(), RenderPassCreationError>30     pub(super) fn validate(
31         device: &Device,
32         create_info: &mut RenderPassCreateInfo,
33     ) -> Result<(), RenderPassCreationError> {
34         let properties = device.physical_device().properties();
35 
36         let RenderPassCreateInfo {
37             attachments,
38             subpasses,
39             dependencies,
40             correlated_view_masks,
41             _ne: _,
42         } = create_info;
43 
44         /*
45             Attachments
46         */
47 
48         let mut attachment_potential_format_features = Vec::with_capacity(attachments.len());
49 
50         for (atch_num, attachment) in attachments.iter().enumerate() {
51             let &AttachmentDescription {
52                 format,
53                 samples,
54                 load_op,
55                 store_op,
56                 stencil_load_op,
57                 stencil_store_op,
58                 initial_layout,
59                 final_layout,
60                 _ne: _,
61             } = attachment;
62             let atch_num = atch_num as u32;
63 
64             // VUID-VkAttachmentDescription2-finalLayout-03061
65             if matches!(
66                 final_layout,
67                 ImageLayout::Undefined | ImageLayout::Preinitialized
68             ) {
69                 return Err(RenderPassCreationError::AttachmentLayoutInvalid {
70                     attachment: atch_num,
71                 });
72             }
73 
74             let format = format.unwrap();
75             let aspects = format.aspects();
76 
77             // VUID-VkAttachmentDescription2-format-parameter
78             format.validate_device(device)?;
79 
80             // VUID-VkAttachmentDescription2-samples-parameter
81             samples.validate_device(device)?;
82 
83             for load_op in [load_op, stencil_load_op] {
84                 // VUID-VkAttachmentDescription2-loadOp-parameter
85                 // VUID-VkAttachmentDescription2-stencilLoadOp-parameter
86                 load_op.validate_device(device)?;
87             }
88 
89             for store_op in [store_op, stencil_store_op] {
90                 // VUID-VkAttachmentDescription2-storeOp-parameter
91                 // VUID-VkAttachmentDescription2-stencilStoreOp-parameter
92                 store_op.validate_device(device)?;
93             }
94 
95             for layout in [initial_layout, final_layout] {
96                 // VUID-VkAttachmentDescription2-initialLayout-parameter
97                 // VUID-VkAttachmentDescription2-finalLayout-parameter
98                 layout.validate_device(device)?;
99 
100                 if aspects.intersects(ImageAspects::DEPTH | ImageAspects::STENCIL) {
101                     // VUID-VkAttachmentDescription2-format-03281
102                     // VUID-VkAttachmentDescription2-format-03283
103                     if matches!(layout, ImageLayout::ColorAttachmentOptimal) {
104                         return Err(RenderPassCreationError::AttachmentLayoutInvalid {
105                             attachment: atch_num,
106                         });
107                     }
108                 } else {
109                     // VUID-VkAttachmentDescription2-format-03280
110                     // VUID-VkAttachmentDescription2-format-03282
111                     // VUID-VkAttachmentDescription2-format-06487
112                     // VUID-VkAttachmentDescription2-format-06488
113                     if matches!(
114                         layout,
115                         ImageLayout::DepthStencilAttachmentOptimal
116                             | ImageLayout::DepthStencilReadOnlyOptimal
117                             | ImageLayout::DepthAttachmentStencilReadOnlyOptimal
118                             | ImageLayout::DepthReadOnlyStencilAttachmentOptimal
119                     ) {
120                         return Err(RenderPassCreationError::AttachmentLayoutInvalid {
121                             attachment: atch_num,
122                         });
123                     }
124                 }
125             }
126 
127             // Use unchecked, because all validation has been done above.
128             attachment_potential_format_features.push(unsafe {
129                 device
130                     .physical_device()
131                     .format_properties_unchecked(format)
132                     .potential_format_features()
133             });
134         }
135 
136         /*
137             Subpasses
138         */
139 
140         // VUID-VkRenderPassCreateInfo2-subpassCount-arraylength
141         assert!(!subpasses.is_empty());
142 
143         let is_multiview = subpasses[0].view_mask != 0;
144 
145         // VUID-VkSubpassDescription2-multiview-06558
146         if is_multiview && !device.enabled_features().multiview {
147             return Err(RenderPassCreationError::RequirementNotMet {
148                 required_for: "`create_info.subpasses[0].view_mask` is not `0`",
149                 requires_one_of: RequiresOneOf {
150                     features: &["multiview"],
151                     ..Default::default()
152                 },
153             });
154         }
155 
156         let mut attachment_used = vec![false; attachments.len()];
157 
158         for (subpass_num, subpass) in subpasses.iter_mut().enumerate() {
159             let &mut SubpassDescription {
160                 view_mask,
161                 ref mut input_attachments,
162                 ref color_attachments,
163                 ref resolve_attachments,
164                 ref depth_stencil_attachment,
165                 ref preserve_attachments,
166                 _ne: _,
167             } = subpass;
168             let subpass_num = subpass_num as u32;
169 
170             // VUID-VkRenderPassCreateInfo2-viewMask-03058
171             if (view_mask != 0) != is_multiview {
172                 return Err(RenderPassCreationError::SubpassMultiviewMismatch {
173                     subpass: subpass_num,
174                     multiview: subpass.view_mask != 0,
175                     first_subpass_multiview: is_multiview,
176                 });
177             }
178 
179             let view_count = u32::BITS - view_mask.leading_zeros();
180 
181             // VUID-VkSubpassDescription2-viewMask-06706
182             if view_count > properties.max_multiview_view_count.unwrap_or(0) {
183                 return Err(
184                     RenderPassCreationError::SubpassMaxMultiviewViewCountExceeded {
185                         subpass: subpass_num,
186                         view_count,
187                         max: properties.max_multiview_view_count.unwrap_or(0),
188                     },
189                 );
190             }
191 
192             // VUID-VkSubpassDescription2-colorAttachmentCount-03063
193             if color_attachments.len() as u32 > properties.max_color_attachments {
194                 return Err(
195                     RenderPassCreationError::SubpassMaxColorAttachmentsExceeded {
196                         subpass: subpass_num,
197                         color_attachment_count: color_attachments.len() as u32,
198                         max: properties.max_color_attachments,
199                     },
200                 );
201             }
202 
203             // Track the layout of each attachment used in this subpass
204             let mut layouts = vec![None; attachments.len()];
205 
206             // Common checks for all attachment types
207             let mut check_attachment = |atch_ref: &AttachmentReference| {
208                 // VUID-VkAttachmentReference2-layout-parameter
209                 atch_ref.layout.validate_device(device)?;
210 
211                 // VUID?
212                 atch_ref.aspects.validate_device(device)?;
213 
214                 // VUID-VkRenderPassCreateInfo2-attachment-03051
215                 let atch = attachments.get(atch_ref.attachment as usize).ok_or(
216                     RenderPassCreationError::SubpassAttachmentOutOfRange {
217                         subpass: subpass_num,
218                         attachment: atch_ref.attachment,
219                     },
220                 )?;
221 
222                 // VUID-VkSubpassDescription2-layout-02528
223                 match &mut layouts[atch_ref.attachment as usize] {
224                     Some(layout) if *layout == atch_ref.layout => (),
225                     Some(_) => {
226                         return Err(RenderPassCreationError::SubpassAttachmentLayoutMismatch {
227                             subpass: subpass_num,
228                             attachment: atch_ref.attachment,
229                         })
230                     }
231                     layout @ None => *layout = Some(atch_ref.layout),
232                 }
233 
234                 let first_use =
235                     !std::mem::replace(&mut attachment_used[atch_ref.attachment as usize], true);
236 
237                 if first_use {
238                     // VUID-VkRenderPassCreateInfo2-pAttachments-02522
239                     if atch.load_op == LoadOp::Clear
240                         && matches!(
241                             atch_ref.layout,
242                             ImageLayout::ShaderReadOnlyOptimal
243                                 | ImageLayout::DepthStencilReadOnlyOptimal
244                                 | ImageLayout::DepthReadOnlyStencilAttachmentOptimal
245                         )
246                     {
247                         return Err(RenderPassCreationError::AttachmentFirstUseLoadOpInvalid {
248                             attachment: atch_ref.attachment,
249                             first_use_subpass: subpass_num,
250                         });
251                     }
252 
253                     // VUID-VkRenderPassCreateInfo2-pAttachments-02523
254                     if atch.stencil_load_op == LoadOp::Clear
255                         && matches!(
256                             atch_ref.layout,
257                             ImageLayout::ShaderReadOnlyOptimal
258                                 | ImageLayout::DepthStencilReadOnlyOptimal
259                                 | ImageLayout::DepthAttachmentStencilReadOnlyOptimal
260                         )
261                     {
262                         return Err(RenderPassCreationError::AttachmentFirstUseLoadOpInvalid {
263                             attachment: atch_ref.attachment,
264                             first_use_subpass: subpass_num,
265                         });
266                     }
267                 }
268 
269                 let potential_format_features =
270                     &attachment_potential_format_features[atch_ref.attachment as usize];
271 
272                 Ok((atch, potential_format_features, first_use))
273             };
274 
275             /*
276                 Check color attachments
277             */
278 
279             let mut color_samples = None;
280 
281             for atch_ref in color_attachments.iter().flatten() {
282                 let (atch, features, _first_use) = check_attachment(atch_ref)?;
283 
284                 // VUID-VkSubpassDescription2-pColorAttachments-02898
285                 if !features.intersects(FormatFeatures::COLOR_ATTACHMENT) {
286                     return Err(
287                         RenderPassCreationError::SubpassAttachmentFormatUsageNotSupported {
288                             subpass: subpass_num,
289                             attachment: atch_ref.attachment,
290                             usage: "color",
291                         },
292                     );
293                 }
294 
295                 // VUID-VkAttachmentReference2-layout-03077
296                 // VUID-VkSubpassDescription2-attachment-06913
297                 // VUID-VkSubpassDescription2-attachment-06916
298                 if matches!(
299                     atch_ref.layout,
300                     ImageLayout::Undefined
301                         | ImageLayout::Preinitialized
302                         | ImageLayout::PresentSrc
303                         | ImageLayout::DepthStencilAttachmentOptimal
304                         | ImageLayout::ShaderReadOnlyOptimal
305                         | ImageLayout::DepthAttachmentStencilReadOnlyOptimal
306                         | ImageLayout::DepthReadOnlyStencilAttachmentOptimal
307                 ) {
308                     return Err(RenderPassCreationError::SubpassAttachmentLayoutInvalid {
309                         subpass: subpass_num,
310                         attachment: atch_ref.attachment,
311                         usage: "color",
312                     });
313                 }
314 
315                 // Not required by spec, but enforced by Vulkano for sanity.
316                 if !atch_ref.aspects.is_empty() {
317                     return Err(RenderPassCreationError::SubpassAttachmentAspectsNotEmpty {
318                         subpass: subpass_num,
319                         attachment: atch_ref.attachment,
320                     });
321                 }
322 
323                 // VUID-VkSubpassDescription2-pColorAttachments-03069
324                 match &mut color_samples {
325                     Some(samples) if *samples == atch.samples => (),
326                     Some(samples) => {
327                         return Err(
328                             RenderPassCreationError::SubpassColorDepthStencilAttachmentSamplesMismatch {
329                                 subpass: subpass_num,
330                                 attachment: atch_ref.attachment,
331                                 samples: atch.samples,
332                                 first_samples: *samples,
333                             },
334                         )
335                     }
336                     samples @ None => *samples = Some(atch.samples),
337                 }
338             }
339 
340             /*
341                 Check depth/stencil attachment
342             */
343 
344             if let Some(atch_ref) = depth_stencil_attachment.as_ref() {
345                 let (atch, features, _first_use) = check_attachment(atch_ref)?;
346 
347                 // VUID-VkSubpassDescription2-pDepthStencilAttachment-02900
348                 if !features.intersects(FormatFeatures::DEPTH_STENCIL_ATTACHMENT) {
349                     return Err(
350                         RenderPassCreationError::SubpassAttachmentFormatUsageNotSupported {
351                             subpass: subpass_num,
352                             attachment: atch_ref.attachment,
353                             usage: "depth/stencil",
354                         },
355                     );
356                 }
357 
358                 // VUID-VkAttachmentReference2-layout-03077
359                 // VUID-VkSubpassDescription2-attachment-06915
360                 if matches!(
361                     atch_ref.layout,
362                     ImageLayout::Undefined
363                         | ImageLayout::Preinitialized
364                         | ImageLayout::PresentSrc
365                         | ImageLayout::ColorAttachmentOptimal
366                         | ImageLayout::ShaderReadOnlyOptimal
367                 ) {
368                     return Err(RenderPassCreationError::SubpassAttachmentLayoutInvalid {
369                         subpass: subpass_num,
370                         attachment: atch_ref.attachment,
371                         usage: "depth/stencil",
372                     });
373                 }
374 
375                 // Not required by spec, but enforced by Vulkano for sanity.
376                 if !atch_ref.aspects.is_empty() {
377                     return Err(RenderPassCreationError::SubpassAttachmentAspectsNotEmpty {
378                         subpass: subpass_num,
379                         attachment: atch_ref.attachment,
380                     });
381                 }
382 
383                 // VUID-VkSubpassDescription2-pDepthStencilAttachment-04440
384                 if color_attachments
385                     .iter()
386                     .flatten()
387                     .any(|color_atch_ref| color_atch_ref.attachment == atch_ref.attachment)
388                 {
389                     return Err(
390                         RenderPassCreationError::SubpassAttachmentUsageColorDepthStencil {
391                             subpass: subpass_num,
392                             attachment: atch_ref.attachment,
393                         },
394                     );
395                 }
396 
397                 // VUID-VkSubpassDescription2-pDepthStencilAttachment-03071
398                 if let Some(samples) = color_samples.filter(|samples| *samples != atch.samples) {
399                     return Err(
400                         RenderPassCreationError::SubpassColorDepthStencilAttachmentSamplesMismatch {
401                             subpass: subpass_num,
402                             attachment: atch_ref.attachment,
403                             samples: atch.samples,
404                             first_samples: samples,
405                         },
406                     );
407                 }
408             }
409 
410             /*
411                 Check input attachments
412                 This must be placed after color and depth/stencil checks so that `first_use`
413                 will be true for VUID-VkSubpassDescription2-loadOp-03064.
414             */
415 
416             for atch_ref in input_attachments.iter_mut().flatten() {
417                 let (atch, features, first_use) = check_attachment(atch_ref)?;
418 
419                 // VUID-VkSubpassDescription2-pInputAttachments-02897
420                 if !features.intersects(
421                     FormatFeatures::COLOR_ATTACHMENT | FormatFeatures::DEPTH_STENCIL_ATTACHMENT,
422                 ) {
423                     return Err(
424                         RenderPassCreationError::SubpassAttachmentFormatUsageNotSupported {
425                             subpass: subpass_num,
426                             attachment: atch_ref.attachment,
427                             usage: "input",
428                         },
429                     );
430                 }
431 
432                 // VUID-VkAttachmentReference2-layout-03077
433                 // VUID-VkSubpassDescription2-attachment-06912
434                 if matches!(
435                     atch_ref.layout,
436                     ImageLayout::Undefined
437                         | ImageLayout::Preinitialized
438                         | ImageLayout::PresentSrc
439                         | ImageLayout::ColorAttachmentOptimal
440                         | ImageLayout::DepthStencilAttachmentOptimal
441                 ) {
442                     return Err(RenderPassCreationError::SubpassAttachmentLayoutInvalid {
443                         subpass: subpass_num,
444                         attachment: atch_ref.attachment,
445                         usage: "input",
446                     });
447                 }
448 
449                 let atch_aspects = atch.format.unwrap().aspects();
450 
451                 if atch_ref.aspects.is_empty() {
452                     // VUID-VkSubpassDescription2-attachment-02800
453                     atch_ref.aspects = atch_aspects;
454                 } else if atch_ref.aspects != atch_aspects {
455                     if !(device.api_version() >= Version::V1_1
456                         || device.enabled_extensions().khr_create_renderpass2
457                         || device.enabled_extensions().khr_maintenance2)
458                     {
459                         return Err(RenderPassCreationError::RequirementNotMet {
460                             required_for: "`create_info.subpasses` has an element, where \
461                                 `input_attachments` has an element that is `Some(atch_ref)`, \
462                                 where `atch_ref.aspects` does not match the aspects of the \
463                                 attachment itself",
464                             requires_one_of: RequiresOneOf {
465                                 api_version: Some(Version::V1_1),
466                                 device_extensions: &["khr_create_renderpass2", "khr_maintenance2"],
467                                 ..Default::default()
468                             },
469                         });
470                     }
471 
472                     // VUID-VkSubpassDescription2-attachment-02801
473                     // VUID-VkSubpassDescription2-attachment-04563
474                     // VUID-VkRenderPassCreateInfo2-attachment-02525
475                     if !atch_aspects.contains(atch_ref.aspects) {
476                         return Err(
477                             RenderPassCreationError::SubpassInputAttachmentAspectsNotCompatible {
478                                 subpass: subpass_num,
479                                 attachment: atch_ref.attachment,
480                             },
481                         );
482                     }
483                 }
484 
485                 // VUID-VkSubpassDescription2-loadOp-03064
486                 if first_use && atch.load_op == LoadOp::Clear {
487                     return Err(RenderPassCreationError::AttachmentFirstUseLoadOpInvalid {
488                         attachment: atch_ref.attachment,
489                         first_use_subpass: subpass_num,
490                     });
491                 }
492             }
493 
494             /*
495                 Check resolve attachments
496             */
497 
498             // VUID-VkSubpassDescription2-pResolveAttachments-parameter
499             if !(resolve_attachments.is_empty()
500                 || resolve_attachments.len() == color_attachments.len())
501             {
502                 return Err(
503                     RenderPassCreationError::SubpassResolveAttachmentsColorAttachmentsLenMismatch {
504                         subpass: subpass_num,
505                     },
506                 );
507             }
508 
509             for (atch_ref, color_atch_ref) in resolve_attachments
510                 .iter()
511                 .zip(subpass.color_attachments.iter())
512                 .filter_map(|(r, c)| r.as_ref().map(|r| (r, c.as_ref())))
513             {
514                 let (atch, features, _first_use) = check_attachment(atch_ref)?;
515 
516                 // VUID-VkSubpassDescription2-pResolveAttachments-02899
517                 if !features.intersects(FormatFeatures::COLOR_ATTACHMENT) {
518                     return Err(
519                         RenderPassCreationError::SubpassAttachmentFormatUsageNotSupported {
520                             subpass: subpass_num,
521                             attachment: atch_ref.attachment,
522                             usage: "resolve",
523                         },
524                     );
525                 }
526 
527                 // VUID-VkAttachmentReference2-layout-03077
528                 // VUID-VkSubpassDescription2-attachment-06914
529                 // VUID-VkSubpassDescription2-attachment-06917
530                 if matches!(
531                     atch_ref.layout,
532                     ImageLayout::Undefined
533                         | ImageLayout::Preinitialized
534                         | ImageLayout::PresentSrc
535                         | ImageLayout::DepthStencilAttachmentOptimal
536                         | ImageLayout::ShaderReadOnlyOptimal
537                         | ImageLayout::DepthAttachmentStencilReadOnlyOptimal
538                         | ImageLayout::DepthReadOnlyStencilAttachmentOptimal
539                 ) {
540                     return Err(RenderPassCreationError::SubpassAttachmentLayoutInvalid {
541                         subpass: subpass_num,
542                         attachment: atch_ref.attachment,
543                         usage: "resolve",
544                     });
545                 }
546 
547                 // Not required by spec, but enforced by Vulkano for sanity.
548                 if !atch_ref.aspects.is_empty() {
549                     return Err(RenderPassCreationError::SubpassAttachmentAspectsNotEmpty {
550                         subpass: subpass_num,
551                         attachment: atch_ref.attachment,
552                     });
553                 }
554 
555                 // VUID-VkSubpassDescription2-pResolveAttachments-03065
556                 let color_atch_ref = color_atch_ref.ok_or({
557                     RenderPassCreationError::SubpassResolveAttachmentWithoutColorAttachment {
558                         subpass: subpass_num,
559                     }
560                 })?;
561                 let color_atch = &attachments[color_atch_ref.attachment as usize];
562 
563                 // VUID-VkSubpassDescription2-pResolveAttachments-03067
564                 if atch.samples != SampleCount::Sample1 {
565                     return Err(
566                         RenderPassCreationError::SubpassResolveAttachmentMultisampled {
567                             subpass: subpass_num,
568                             attachment: atch_ref.attachment,
569                         },
570                     );
571                 }
572 
573                 // VUID-VkSubpassDescription2-pResolveAttachments-03066
574                 if color_atch.samples == SampleCount::Sample1 {
575                     return Err(
576                         RenderPassCreationError::SubpassColorAttachmentWithResolveNotMultisampled {
577                             subpass: subpass_num,
578                             attachment: atch_ref.attachment,
579                         },
580                     );
581                 }
582 
583                 // VUID-VkSubpassDescription2-pResolveAttachments-03068
584                 if atch.format != color_atch.format {
585                     return Err(
586                         RenderPassCreationError::SubpassResolveAttachmentFormatMismatch {
587                             subpass: subpass_num,
588                             resolve_attachment: atch_ref.attachment,
589                             color_attachment: color_atch_ref.attachment,
590                         },
591                     );
592                 }
593             }
594 
595             /*
596                 Check preserve attachments
597             */
598 
599             for &atch in preserve_attachments {
600                 // VUID-VkRenderPassCreateInfo2-attachment-03051
601                 if atch as usize >= attachments.len() {
602                     return Err(RenderPassCreationError::SubpassAttachmentOutOfRange {
603                         subpass: subpass_num,
604                         attachment: atch,
605                     });
606                 }
607 
608                 // VUID-VkSubpassDescription2-pPreserveAttachments-03074
609                 if layouts[atch as usize].is_some() {
610                     return Err(
611                         RenderPassCreationError::SubpassPreserveAttachmentUsedElsewhere {
612                             subpass: subpass_num,
613                             attachment: atch,
614                         },
615                     );
616                 }
617             }
618         }
619 
620         /*
621             Dependencies
622         */
623 
624         for (dependency_num, dependency) in dependencies.iter().enumerate() {
625             let &SubpassDependency {
626                 src_subpass,
627                 dst_subpass,
628                 src_stages,
629                 dst_stages,
630                 src_access,
631                 dst_access,
632                 dependency_flags,
633                 view_offset,
634                 _ne: _,
635             } = dependency;
636             let dependency_num = dependency_num as u32;
637 
638             for (stages, access) in [(src_stages, src_access), (dst_stages, dst_access)] {
639                 if !device.enabled_features().synchronization2 {
640                     if stages.is_2() {
641                         return Err(RenderPassCreationError::RequirementNotMet {
642                             required_for: "`create_info.dependencies` has an element where \
643                                 `src_stages` or `dst_stages` contains flags from \
644                                 `VkPipelineStageFlagBits2`",
645                             requires_one_of: RequiresOneOf {
646                                 features: &["synchronization2"],
647                                 ..Default::default()
648                             },
649                         });
650                     }
651 
652                     if access.is_2() {
653                         return Err(RenderPassCreationError::RequirementNotMet {
654                             required_for: "`create_info.dependencies` has an element where \
655                                 `src_access` or `dst_access` contains flags from \
656                                 `VkAccessFlagBits2`",
657                             requires_one_of: RequiresOneOf {
658                                 features: &["synchronization2"],
659                                 ..Default::default()
660                             },
661                         });
662                     }
663                 } else if !(device.api_version() >= Version::V1_2
664                     || device.enabled_extensions().khr_create_renderpass2)
665                 {
666                     // If synchronization2 is enabled but we don't have create_renderpass2,
667                     // we are unable to use extension structs, so we can't use the
668                     // extra flag bits.
669 
670                     if stages.is_2() {
671                         return Err(RenderPassCreationError::RequirementNotMet {
672                             required_for: "`create_info.dependencies` has an element where \
673                                 `src_stages` or `dst_stages` contains flags from \
674                                 `VkPipelineStageFlagBits2`",
675                             requires_one_of: RequiresOneOf {
676                                 api_version: Some(Version::V1_2),
677                                 device_extensions: &["khr_create_renderpass2"],
678                                 ..Default::default()
679                             },
680                         });
681                     }
682 
683                     if access.is_2() {
684                         return Err(RenderPassCreationError::RequirementNotMet {
685                             required_for: "`create_info.dependencies` has an element where \
686                                 `src_access` or `dst_access` contains flags from \
687                                 `VkAccessFlagBits2`",
688                             requires_one_of: RequiresOneOf {
689                                 api_version: Some(Version::V1_2),
690                                 device_extensions: &["khr_create_renderpass2"],
691                                 ..Default::default()
692                             },
693                         });
694                     }
695                 }
696 
697                 // VUID-VkMemoryBarrier2-srcStageMask-parameter
698                 // VUID-VkMemoryBarrier2-dstStageMask-parameter
699                 stages.validate_device(device)?;
700 
701                 // VUID-VkMemoryBarrier2-srcAccessMask-parameter
702                 // VUID-VkMemoryBarrier2-dstAccessMask-parameter
703                 access.validate_device(device)?;
704 
705                 // VUID-VkMemoryBarrier2-srcStageMask-03929
706                 // VUID-VkMemoryBarrier2-dstStageMask-03929
707                 if stages.intersects(PipelineStages::GEOMETRY_SHADER)
708                     && !device.enabled_features().geometry_shader
709                 {
710                     return Err(RenderPassCreationError::RequirementNotMet {
711                         required_for: "`create_info.dependencies` has an element where `stages` \
712                             contains `PipelineStages::GEOMETRY_SHADER`",
713                         requires_one_of: RequiresOneOf {
714                             features: &["geometry_shader"],
715                             ..Default::default()
716                         },
717                     });
718                 }
719 
720                 // VUID-VkMemoryBarrier2-srcStageMask-03930
721                 // VUID-VkMemoryBarrier2-dstStageMask-03930
722                 if stages.intersects(
723                     PipelineStages::TESSELLATION_CONTROL_SHADER
724                         | PipelineStages::TESSELLATION_EVALUATION_SHADER,
725                 ) && !device.enabled_features().tessellation_shader
726                 {
727                     return Err(RenderPassCreationError::RequirementNotMet {
728                         required_for: "`create_info.dependencies` has an element where `stages` \
729                             contains `PipelineStages::TESSELLATION_CONTROL_SHADER` or \
730                             `PipelineStages::TESSELLATION_EVALUATION_SHADER`",
731                         requires_one_of: RequiresOneOf {
732                             features: &["tessellation_shader"],
733                             ..Default::default()
734                         },
735                     });
736                 }
737 
738                 // VUID-VkMemoryBarrier2-srcStageMask-03931
739                 // VUID-VkMemoryBarrier2-dstStageMask-03931
740                 if stages.intersects(PipelineStages::CONDITIONAL_RENDERING)
741                     && !device.enabled_features().conditional_rendering
742                 {
743                     return Err(RenderPassCreationError::RequirementNotMet {
744                         required_for: "`create_info.dependencies` has an element where `stages` \
745                             contains `PipelineStages::CONDITIONAL_RENDERING`",
746                         requires_one_of: RequiresOneOf {
747                             features: &["conditional_rendering"],
748                             ..Default::default()
749                         },
750                     });
751                 }
752 
753                 // VUID-VkMemoryBarrier2-srcStageMask-03932
754                 // VUID-VkMemoryBarrier2-dstStageMask-03932
755                 if stages.intersects(PipelineStages::FRAGMENT_DENSITY_PROCESS)
756                     && !device.enabled_features().fragment_density_map
757                 {
758                     return Err(RenderPassCreationError::RequirementNotMet {
759                         required_for: "`create_info.dependencies` has an element where `stages` \
760                             contains `PipelineStages::FRAGMENT_DENSITY_PROCESS`",
761                         requires_one_of: RequiresOneOf {
762                             features: &["fragment_density_map"],
763                             ..Default::default()
764                         },
765                     });
766                 }
767 
768                 // VUID-VkMemoryBarrier2-srcStageMask-03933
769                 // VUID-VkMemoryBarrier2-dstStageMask-03933
770                 if stages.intersects(PipelineStages::TRANSFORM_FEEDBACK)
771                     && !device.enabled_features().transform_feedback
772                 {
773                     return Err(RenderPassCreationError::RequirementNotMet {
774                         required_for: "`create_info.dependencies` has an element where `stages` \
775                             contains `PipelineStages::TRANSFORM_FEEDBACK`",
776                         requires_one_of: RequiresOneOf {
777                             features: &["transform_feedback"],
778                             ..Default::default()
779                         },
780                     });
781                 }
782 
783                 // VUID-VkMemoryBarrier2-srcStageMask-03934
784                 // VUID-VkMemoryBarrier2-dstStageMask-03934
785                 if stages.intersects(PipelineStages::MESH_SHADER)
786                     && !device.enabled_features().mesh_shader
787                 {
788                     return Err(RenderPassCreationError::RequirementNotMet {
789                         required_for: "`create_info.dependencies` has an element where `stages` \
790                             contains `PipelineStages::MESH_SHADER`",
791                         requires_one_of: RequiresOneOf {
792                             features: &["mesh_shader"],
793                             ..Default::default()
794                         },
795                     });
796                 }
797 
798                 // VUID-VkMemoryBarrier2-srcStageMask-03935
799                 // VUID-VkMemoryBarrier2-dstStageMask-03935
800                 if stages.intersects(PipelineStages::TASK_SHADER)
801                     && !device.enabled_features().task_shader
802                 {
803                     return Err(RenderPassCreationError::RequirementNotMet {
804                         required_for: "`create_info.dependencies` has an element where `stages` \
805                             contains `PipelineStages::TASK_SHADER`",
806                         requires_one_of: RequiresOneOf {
807                             features: &["task_shader"],
808                             ..Default::default()
809                         },
810                     });
811                 }
812 
813                 // VUID-VkMemoryBarrier2-shadingRateImage-07316
814                 // VUID-VkMemoryBarrier2-shadingRateImage-07316
815                 if stages.intersects(PipelineStages::FRAGMENT_SHADING_RATE_ATTACHMENT)
816                     && !(device.enabled_features().attachment_fragment_shading_rate
817                         || device.enabled_features().shading_rate_image)
818                 {
819                     return Err(RenderPassCreationError::RequirementNotMet {
820                         required_for: "`create_info.dependencies` has an element where `stages` \
821                             contains `PipelineStages::FRAGMENT_SHADING_RATE_ATTACHMENT`",
822                         requires_one_of: RequiresOneOf {
823                             features: &["attachment_fragment_shading_rate", "shading_rate_image"],
824                             ..Default::default()
825                         },
826                     });
827                 }
828 
829                 // VUID-VkMemoryBarrier2-srcStageMask-04957
830                 // VUID-VkMemoryBarrier2-dstStageMask-04957
831                 if stages.intersects(PipelineStages::SUBPASS_SHADING)
832                     && !device.enabled_features().subpass_shading
833                 {
834                     return Err(RenderPassCreationError::RequirementNotMet {
835                         required_for: "`create_info.dependencies` has an element where `stages` \
836                             contains `PipelineStages::SUBPASS_SHADING`",
837                         requires_one_of: RequiresOneOf {
838                             features: &["subpass_shading"],
839                             ..Default::default()
840                         },
841                     });
842                 }
843 
844                 // VUID-VkMemoryBarrier2-srcStageMask-04995
845                 // VUID-VkMemoryBarrier2-dstStageMask-04995
846                 if stages.intersects(PipelineStages::INVOCATION_MASK)
847                     && !device.enabled_features().invocation_mask
848                 {
849                     return Err(RenderPassCreationError::RequirementNotMet {
850                         required_for: "`create_info.dependencies` has an element where `stages` \
851                             contains `PipelineStages::INVOCATION_MASK`",
852                         requires_one_of: RequiresOneOf {
853                             features: &["invocation_mask"],
854                             ..Default::default()
855                         },
856                     });
857                 }
858 
859                 // VUID-VkSubpassDependency2-srcStageMask-03937
860                 // VUID-VkSubpassDependency2-dstStageMask-03937
861                 if stages.is_empty() && !device.enabled_features().synchronization2 {
862                     return Err(RenderPassCreationError::RequirementNotMet {
863                         required_for: "`create_info.dependencies` has an element where `stages` \
864                             is empty",
865                         requires_one_of: RequiresOneOf {
866                             features: &["synchronization2"],
867                             ..Default::default()
868                         },
869                     });
870                 }
871 
872                 // VUID-VkSubpassDependency2-srcAccessMask-03088
873                 // VUID-VkSubpassDependency2-dstAccessMask-03089
874                 if !AccessFlags::from(stages).contains(access) {
875                     return Err(
876                         RenderPassCreationError::DependencyAccessNotSupportedByStages {
877                             dependency: dependency_num,
878                         },
879                     );
880                 }
881             }
882 
883             if dependency_flags.intersects(DependencyFlags::VIEW_LOCAL) {
884                 // VUID-VkRenderPassCreateInfo2-viewMask-03059
885                 if !is_multiview {
886                     return Err(
887                         RenderPassCreationError::DependencyViewLocalMultiviewNotEnabled {
888                             dependency: dependency_num,
889                         },
890                     );
891                 }
892             } else {
893                 // VUID-VkSubpassDependency2-dependencyFlags-03092
894                 if view_offset != 0 {
895                     return Err(
896                         RenderPassCreationError::DependencyViewOffzetNonzeroWithoutViewLocal {
897                             dependency: dependency_num,
898                         },
899                     );
900                 }
901             }
902 
903             // VUID-VkSubpassDependency2-srcSubpass-03085
904             if src_subpass.is_none() && dst_subpass.is_none() {
905                 return Err(RenderPassCreationError::DependencyBothSubpassesExternal {
906                     dependency: dependency_num,
907                 });
908             }
909 
910             for (subpass, stages) in [(src_subpass, src_stages), (dst_subpass, dst_stages)] {
911                 if let Some(subpass) = subpass {
912                     // VUID-VkRenderPassCreateInfo2-srcSubpass-02526
913                     // VUID-VkRenderPassCreateInfo2-dstSubpass-02527
914                     if subpass as usize >= subpasses.len() {
915                         return Err(RenderPassCreationError::DependencySubpassOutOfRange {
916                             dependency: dependency_num,
917                             subpass,
918                         });
919                     }
920 
921                     let remaining_stages = stages
922                         - (PipelineStages::DRAW_INDIRECT
923                             | PipelineStages::INDEX_INPUT
924                             | PipelineStages::VERTEX_ATTRIBUTE_INPUT
925                             | PipelineStages::VERTEX_SHADER
926                             | PipelineStages::TESSELLATION_CONTROL_SHADER
927                             | PipelineStages::TESSELLATION_EVALUATION_SHADER
928                             | PipelineStages::GEOMETRY_SHADER
929                             | PipelineStages::TRANSFORM_FEEDBACK
930                             | PipelineStages::FRAGMENT_SHADING_RATE_ATTACHMENT
931                             | PipelineStages::EARLY_FRAGMENT_TESTS
932                             | PipelineStages::FRAGMENT_SHADER
933                             | PipelineStages::LATE_FRAGMENT_TESTS
934                             | PipelineStages::COLOR_ATTACHMENT_OUTPUT
935                             | PipelineStages::ALL_GRAPHICS);
936 
937                     // VUID-VkRenderPassCreateInfo2-pDependencies-03054
938                     // VUID-VkRenderPassCreateInfo2-pDependencies-03055
939                     if !remaining_stages.is_empty() {
940                         return Err(RenderPassCreationError::DependencyStageNotSupported {
941                             dependency: dependency_num,
942                         });
943                     }
944                 } else {
945                     // VUID-VkSubpassDependency2-dependencyFlags-03090
946                     // VUID-VkSubpassDependency2-dependencyFlags-03091
947                     if dependency_flags.intersects(DependencyFlags::VIEW_LOCAL) {
948                         return Err(
949                             RenderPassCreationError::DependencyViewLocalExternalDependency {
950                                 dependency: dependency_num,
951                             },
952                         );
953                     }
954                 }
955             }
956 
957             if let (Some(src_subpass), Some(dst_subpass)) = (src_subpass, dst_subpass) {
958                 // VUID-VkSubpassDependency2-srcSubpass-03084
959                 if src_subpass > dst_subpass {
960                     return Err(
961                         RenderPassCreationError::DependencySourceSubpassAfterDestinationSubpass {
962                             dependency: dependency_num,
963                         },
964                     );
965                 }
966 
967                 if src_subpass == dst_subpass {
968                     let framebuffer_stages = PipelineStages::EARLY_FRAGMENT_TESTS
969                         | PipelineStages::FRAGMENT_SHADER
970                         | PipelineStages::LATE_FRAGMENT_TESTS
971                         | PipelineStages::COLOR_ATTACHMENT_OUTPUT;
972 
973                     // VUID-VkSubpassDependency2-srcSubpass-06810
974                     if src_stages.intersects(framebuffer_stages)
975                         && !(dst_stages - framebuffer_stages).is_empty()
976                     {
977                         return Err(
978                             RenderPassCreationError::DependencySelfDependencySourceStageAfterDestinationStage {
979                                 dependency: dependency_num,
980                             },
981                         );
982                     }
983 
984                     // VUID-VkSubpassDependency2-srcSubpass-02245
985                     if src_stages.intersects(framebuffer_stages)
986                         && dst_stages.intersects(framebuffer_stages)
987                         && !dependency_flags.intersects(DependencyFlags::BY_REGION)
988                     {
989                         return Err(
990                             RenderPassCreationError::DependencySelfDependencyFramebufferStagesWithoutByRegion {
991                                 dependency: dependency_num,
992                             },
993                         );
994                     }
995 
996                     if dependency_flags.intersects(DependencyFlags::VIEW_LOCAL) {
997                         // VUID-VkSubpassDependency2-viewOffset-02530
998                         if view_offset != 0 {
999                             return Err(
1000                                 RenderPassCreationError::DependencySelfDependencyViewLocalNonzeroViewOffset {
1001                                     dependency: dependency_num,
1002                                 },
1003                             );
1004                         }
1005                     } else {
1006                         // VUID-VkRenderPassCreateInfo2-pDependencies-03060
1007                         if subpasses[src_subpass as usize].view_mask.count_ones() > 1 {
1008                             return Err(
1009                                 RenderPassCreationError::DependencySelfDependencyViewMaskMultiple {
1010                                     dependency: dependency_num,
1011                                     subpass: src_subpass,
1012                                 },
1013                             );
1014                         }
1015                     }
1016                 }
1017             }
1018         }
1019 
1020         /*
1021             Correlated view masks
1022         */
1023 
1024         // VUID-VkRenderPassCreateInfo2-viewMask-03057
1025         if !correlated_view_masks.is_empty() {
1026             if !is_multiview {
1027                 return Err(RenderPassCreationError::CorrelatedViewMasksMultiviewNotEnabled);
1028             }
1029 
1030             // VUID-VkRenderPassCreateInfo2-pCorrelatedViewMasks-03056
1031             correlated_view_masks.iter().try_fold(0, |total, &mask| {
1032                 if total & mask != 0 {
1033                     Err(RenderPassCreationError::CorrelatedViewMasksOverlapping)
1034                 } else {
1035                     Ok(total | mask)
1036                 }
1037             })?;
1038         }
1039 
1040         Ok(())
1041     }
1042 
create_v2( device: &Device, create_info: &RenderPassCreateInfo, ) -> Result<ash::vk::RenderPass, RenderPassCreationError>1043     pub(super) unsafe fn create_v2(
1044         device: &Device,
1045         create_info: &RenderPassCreateInfo,
1046     ) -> Result<ash::vk::RenderPass, RenderPassCreationError> {
1047         let RenderPassCreateInfo {
1048             attachments,
1049             subpasses,
1050             dependencies,
1051             correlated_view_masks,
1052             _ne: _,
1053         } = create_info;
1054 
1055         let attachments_vk = attachments
1056             .iter()
1057             .map(|attachment| ash::vk::AttachmentDescription2 {
1058                 flags: ash::vk::AttachmentDescriptionFlags::empty(),
1059                 format: attachment
1060                     .format
1061                     .map_or(ash::vk::Format::UNDEFINED, |f| f.into()),
1062                 samples: attachment.samples.into(),
1063                 load_op: attachment.load_op.into(),
1064                 store_op: attachment.store_op.into(),
1065                 stencil_load_op: attachment.stencil_load_op.into(),
1066                 stencil_store_op: attachment.stencil_store_op.into(),
1067                 initial_layout: attachment.initial_layout.into(),
1068                 final_layout: attachment.final_layout.into(),
1069                 ..Default::default()
1070             })
1071             .collect::<SmallVec<[_; 4]>>();
1072 
1073         let attachment_references_vk = subpasses
1074             .iter()
1075             .flat_map(|subpass| {
1076                 (subpass.input_attachments.iter())
1077                     .chain(subpass.color_attachments.iter())
1078                     .chain(subpass.resolve_attachments.iter())
1079                     .map(Option::as_ref)
1080                     .chain(subpass.depth_stencil_attachment.iter().map(Some))
1081                     .map(|atch_ref| {
1082                         if let Some(atch_ref) = atch_ref {
1083                             ash::vk::AttachmentReference2 {
1084                                 attachment: atch_ref.attachment,
1085                                 layout: atch_ref.layout.into(),
1086                                 aspect_mask: atch_ref.aspects.into(),
1087                                 ..Default::default()
1088                             }
1089                         } else {
1090                             ash::vk::AttachmentReference2 {
1091                                 attachment: ash::vk::ATTACHMENT_UNUSED,
1092                                 ..Default::default()
1093                             }
1094                         }
1095                     })
1096             })
1097             .collect::<SmallVec<[_; 8]>>();
1098 
1099         let subpasses_vk = {
1100             // `ref_index` is increased during the loop and points to the next element to use
1101             // in `attachment_references_vk`.
1102             let mut ref_index = 0usize;
1103             let out: SmallVec<[_; 4]> = subpasses
1104                 .iter()
1105                 .map(|subpass| {
1106                     let input_attachments = attachment_references_vk.as_ptr().add(ref_index);
1107                     ref_index += subpass.input_attachments.len();
1108                     let color_attachments = attachment_references_vk.as_ptr().add(ref_index);
1109                     ref_index += subpass.color_attachments.len();
1110                     let resolve_attachments = attachment_references_vk.as_ptr().add(ref_index);
1111                     ref_index += subpass.resolve_attachments.len();
1112                     let depth_stencil = if subpass.depth_stencil_attachment.is_some() {
1113                         let a = attachment_references_vk.as_ptr().add(ref_index);
1114                         ref_index += 1;
1115                         a
1116                     } else {
1117                         ptr::null()
1118                     };
1119 
1120                     ash::vk::SubpassDescription2 {
1121                         flags: ash::vk::SubpassDescriptionFlags::empty(),
1122                         pipeline_bind_point: ash::vk::PipelineBindPoint::GRAPHICS, // TODO: any need to make this user-specifiable?
1123                         view_mask: subpass.view_mask,
1124                         input_attachment_count: subpass.input_attachments.len() as u32,
1125                         p_input_attachments: if subpass.input_attachments.is_empty() {
1126                             ptr::null()
1127                         } else {
1128                             input_attachments
1129                         },
1130                         color_attachment_count: subpass.color_attachments.len() as u32,
1131                         p_color_attachments: if subpass.color_attachments.is_empty() {
1132                             ptr::null()
1133                         } else {
1134                             color_attachments
1135                         },
1136                         p_resolve_attachments: if subpass.resolve_attachments.is_empty() {
1137                             ptr::null()
1138                         } else {
1139                             resolve_attachments
1140                         },
1141                         p_depth_stencil_attachment: depth_stencil,
1142                         preserve_attachment_count: subpass.preserve_attachments.len() as u32,
1143                         p_preserve_attachments: if subpass.preserve_attachments.is_empty() {
1144                             ptr::null()
1145                         } else {
1146                             subpass.preserve_attachments.as_ptr()
1147                         },
1148                         ..Default::default()
1149                     }
1150                 })
1151                 .collect();
1152 
1153             // If this assertion fails, there's a serious bug in the code above ^.
1154             debug_assert!(ref_index == attachment_references_vk.len());
1155 
1156             out
1157         };
1158 
1159         let memory_barriers_vk: SmallVec<[_; 4]> = if device.enabled_features().synchronization2 {
1160             debug_assert!(
1161                 device.api_version() >= Version::V1_3
1162                     || device.enabled_extensions().khr_synchronization2
1163             );
1164             dependencies
1165                 .iter()
1166                 .map(|dependency| ash::vk::MemoryBarrier2 {
1167                     src_stage_mask: dependency.src_stages.into(),
1168                     src_access_mask: dependency.src_access.into(),
1169                     dst_stage_mask: dependency.dst_stages.into(),
1170                     dst_access_mask: dependency.dst_access.into(),
1171                     ..Default::default()
1172                 })
1173                 .collect()
1174         } else {
1175             SmallVec::new()
1176         };
1177 
1178         let dependencies_vk = dependencies
1179             .iter()
1180             .enumerate()
1181             .map(|(index, dependency)| {
1182                 ash::vk::SubpassDependency2 {
1183                     p_next: memory_barriers_vk
1184                         .get(index)
1185                         .map_or(ptr::null(), |mb| mb as *const _ as *const _),
1186                     src_subpass: dependency.src_subpass.unwrap_or(ash::vk::SUBPASS_EXTERNAL),
1187                     dst_subpass: dependency.dst_subpass.unwrap_or(ash::vk::SUBPASS_EXTERNAL),
1188                     src_stage_mask: dependency.src_stages.into(),
1189                     dst_stage_mask: dependency.dst_stages.into(),
1190                     src_access_mask: dependency.src_access.into(),
1191                     dst_access_mask: dependency.dst_access.into(),
1192                     dependency_flags: dependency.dependency_flags.into(),
1193                     // VUID-VkSubpassDependency2-dependencyFlags-03092
1194                     view_offset: dependency.view_offset,
1195                     ..Default::default()
1196                 }
1197             })
1198             .collect::<SmallVec<[_; 4]>>();
1199 
1200         let create_info = ash::vk::RenderPassCreateInfo2 {
1201             flags: ash::vk::RenderPassCreateFlags::empty(),
1202             attachment_count: attachments_vk.len() as u32,
1203             p_attachments: if attachments_vk.is_empty() {
1204                 ptr::null()
1205             } else {
1206                 attachments_vk.as_ptr()
1207             },
1208             subpass_count: subpasses_vk.len() as u32,
1209             p_subpasses: if subpasses_vk.is_empty() {
1210                 ptr::null()
1211             } else {
1212                 subpasses_vk.as_ptr()
1213             },
1214             dependency_count: dependencies_vk.len() as u32,
1215             p_dependencies: if dependencies_vk.is_empty() {
1216                 ptr::null()
1217             } else {
1218                 dependencies_vk.as_ptr()
1219             },
1220             correlated_view_mask_count: correlated_view_masks.len() as u32,
1221             p_correlated_view_masks: correlated_view_masks.as_ptr(),
1222             ..Default::default()
1223         };
1224 
1225         Ok({
1226             let fns = device.fns();
1227             let mut output = MaybeUninit::uninit();
1228 
1229             if device.api_version() >= Version::V1_2 {
1230                 (fns.v1_2.create_render_pass2)(
1231                     device.handle(),
1232                     &create_info,
1233                     ptr::null(),
1234                     output.as_mut_ptr(),
1235                 )
1236             } else {
1237                 (fns.khr_create_renderpass2.create_render_pass2_khr)(
1238                     device.handle(),
1239                     &create_info,
1240                     ptr::null(),
1241                     output.as_mut_ptr(),
1242                 )
1243             }
1244             .result()
1245             .map_err(VulkanError::from)?;
1246 
1247             output.assume_init()
1248         })
1249     }
1250 
create_v1( device: &Device, create_info: &RenderPassCreateInfo, ) -> Result<ash::vk::RenderPass, RenderPassCreationError>1251     pub(super) unsafe fn create_v1(
1252         device: &Device,
1253         create_info: &RenderPassCreateInfo,
1254     ) -> Result<ash::vk::RenderPass, RenderPassCreationError> {
1255         let RenderPassCreateInfo {
1256             attachments,
1257             subpasses,
1258             dependencies,
1259             correlated_view_masks,
1260             _ne: _,
1261         } = create_info;
1262 
1263         let attachments_vk = attachments
1264             .iter()
1265             .map(|attachment| ash::vk::AttachmentDescription {
1266                 flags: ash::vk::AttachmentDescriptionFlags::empty(),
1267                 format: attachment
1268                     .format
1269                     .map_or(ash::vk::Format::UNDEFINED, |f| f.into()),
1270                 samples: attachment.samples.into(),
1271                 load_op: attachment.load_op.into(),
1272                 store_op: attachment.store_op.into(),
1273                 stencil_load_op: attachment.stencil_load_op.into(),
1274                 stencil_store_op: attachment.stencil_store_op.into(),
1275                 initial_layout: attachment.initial_layout.into(),
1276                 final_layout: attachment.final_layout.into(),
1277             })
1278             .collect::<SmallVec<[_; 4]>>();
1279 
1280         let attachment_references_vk = subpasses
1281             .iter()
1282             .flat_map(|subpass| {
1283                 (subpass.input_attachments.iter())
1284                     .chain(subpass.color_attachments.iter())
1285                     .chain(subpass.resolve_attachments.iter())
1286                     .map(Option::as_ref)
1287                     .chain(subpass.depth_stencil_attachment.iter().map(Some))
1288                     .map(|atch_ref| {
1289                         if let Some(atch_ref) = atch_ref {
1290                             ash::vk::AttachmentReference {
1291                                 attachment: atch_ref.attachment,
1292                                 layout: atch_ref.layout.into(),
1293                             }
1294                         } else {
1295                             ash::vk::AttachmentReference {
1296                                 attachment: ash::vk::ATTACHMENT_UNUSED,
1297                                 layout: Default::default(),
1298                             }
1299                         }
1300                     })
1301             })
1302             .collect::<SmallVec<[_; 8]>>();
1303 
1304         let subpasses_vk = {
1305             // `ref_index` is increased during the loop and points to the next element to use
1306             // in `attachment_references_vk`.
1307             let mut ref_index = 0usize;
1308             let out: SmallVec<[_; 4]> = subpasses
1309                 .iter()
1310                 .map(|subpass| {
1311                     let input_attachments = attachment_references_vk.as_ptr().add(ref_index);
1312                     ref_index += subpass.input_attachments.len();
1313                     let color_attachments = attachment_references_vk.as_ptr().add(ref_index);
1314                     ref_index += subpass.color_attachments.len();
1315                     let resolve_attachments = attachment_references_vk.as_ptr().add(ref_index);
1316                     ref_index += subpass.resolve_attachments.len();
1317                     let depth_stencil = if subpass.depth_stencil_attachment.is_some() {
1318                         let a = attachment_references_vk.as_ptr().add(ref_index);
1319                         ref_index += 1;
1320                         a
1321                     } else {
1322                         ptr::null()
1323                     };
1324 
1325                     ash::vk::SubpassDescription {
1326                         flags: ash::vk::SubpassDescriptionFlags::empty(),
1327                         pipeline_bind_point: ash::vk::PipelineBindPoint::GRAPHICS,
1328                         input_attachment_count: subpass.input_attachments.len() as u32,
1329                         p_input_attachments: if subpass.input_attachments.is_empty() {
1330                             ptr::null()
1331                         } else {
1332                             input_attachments
1333                         },
1334                         color_attachment_count: subpass.color_attachments.len() as u32,
1335                         p_color_attachments: if subpass.color_attachments.is_empty() {
1336                             ptr::null()
1337                         } else {
1338                             color_attachments
1339                         },
1340                         p_resolve_attachments: if subpass.resolve_attachments.is_empty() {
1341                             ptr::null()
1342                         } else {
1343                             resolve_attachments
1344                         },
1345                         p_depth_stencil_attachment: depth_stencil,
1346                         preserve_attachment_count: subpass.preserve_attachments.len() as u32,
1347                         p_preserve_attachments: if subpass.preserve_attachments.is_empty() {
1348                             ptr::null()
1349                         } else {
1350                             subpass.preserve_attachments.as_ptr()
1351                         },
1352                     }
1353                 })
1354                 .collect();
1355 
1356             // If this assertion fails, there's a serious bug in the code above ^.
1357             debug_assert!(ref_index == attachment_references_vk.len());
1358 
1359             out
1360         };
1361 
1362         let dependencies_vk = dependencies
1363             .iter()
1364             .map(|dependency| ash::vk::SubpassDependency {
1365                 src_subpass: dependency.src_subpass.unwrap_or(ash::vk::SUBPASS_EXTERNAL),
1366                 dst_subpass: dependency.dst_subpass.unwrap_or(ash::vk::SUBPASS_EXTERNAL),
1367                 src_stage_mask: dependency.src_stages.into(),
1368                 dst_stage_mask: dependency.dst_stages.into(),
1369                 src_access_mask: dependency.src_access.into(),
1370                 dst_access_mask: dependency.dst_access.into(),
1371                 dependency_flags: dependency.dependency_flags.into(),
1372             })
1373             .collect::<SmallVec<[_; 4]>>();
1374 
1375         /* Input attachment aspect */
1376 
1377         let input_attachment_aspect_references: SmallVec<[_; 8]> = if device.api_version()
1378             >= Version::V1_1
1379             || device.enabled_extensions().khr_maintenance2
1380         {
1381             subpasses
1382                 .iter()
1383                 .enumerate()
1384                 .flat_map(|(subpass_num, subpass)| {
1385                     subpass.input_attachments.iter().enumerate().flat_map(
1386                         move |(atch_num, atch_ref)| {
1387                             atch_ref.as_ref().map(|atch_ref| {
1388                                 ash::vk::InputAttachmentAspectReference {
1389                                     subpass: subpass_num as u32,
1390                                     input_attachment_index: atch_num as u32,
1391                                     aspect_mask: atch_ref.aspects.into(),
1392                                 }
1393                             })
1394                         },
1395                     )
1396                 })
1397                 .collect()
1398         } else {
1399             SmallVec::new()
1400         };
1401 
1402         let mut input_attachment_aspect_create_info =
1403             if !input_attachment_aspect_references.is_empty() {
1404                 Some(ash::vk::RenderPassInputAttachmentAspectCreateInfo {
1405                     aspect_reference_count: input_attachment_aspect_references.len() as u32,
1406                     p_aspect_references: input_attachment_aspect_references.as_ptr(),
1407                     ..Default::default()
1408                 })
1409             } else {
1410                 None
1411             };
1412 
1413         /* Multiview */
1414 
1415         let is_multiview = subpasses[0].view_mask != 0;
1416 
1417         let (multiview_view_masks, multiview_view_offsets): (SmallVec<[_; 4]>, SmallVec<[_; 4]>) =
1418             if is_multiview {
1419                 (
1420                     subpasses.iter().map(|subpass| subpass.view_mask).collect(),
1421                     dependencies
1422                         .iter()
1423                         .map(|dependency| dependency.view_offset)
1424                         .collect(),
1425                 )
1426             } else {
1427                 (SmallVec::new(), SmallVec::new())
1428             };
1429 
1430         let mut multiview_create_info = if is_multiview {
1431             debug_assert!(multiview_view_masks.len() == subpasses.len());
1432             debug_assert!(multiview_view_offsets.len() == dependencies.len());
1433 
1434             Some(ash::vk::RenderPassMultiviewCreateInfo {
1435                 subpass_count: multiview_view_masks.len() as u32,
1436                 p_view_masks: multiview_view_masks.as_ptr(),
1437                 dependency_count: multiview_view_offsets.len() as u32,
1438                 p_view_offsets: multiview_view_offsets.as_ptr(),
1439                 correlation_mask_count: correlated_view_masks.len() as u32,
1440                 p_correlation_masks: correlated_view_masks.as_ptr(),
1441                 ..Default::default()
1442             })
1443         } else {
1444             None
1445         };
1446 
1447         /* Create */
1448 
1449         let mut create_info = ash::vk::RenderPassCreateInfo {
1450             flags: ash::vk::RenderPassCreateFlags::empty(),
1451             attachment_count: attachments_vk.len() as u32,
1452             p_attachments: if attachments_vk.is_empty() {
1453                 ptr::null()
1454             } else {
1455                 attachments_vk.as_ptr()
1456             },
1457             subpass_count: subpasses_vk.len() as u32,
1458             p_subpasses: if subpasses_vk.is_empty() {
1459                 ptr::null()
1460             } else {
1461                 subpasses_vk.as_ptr()
1462             },
1463             dependency_count: dependencies_vk.len() as u32,
1464             p_dependencies: if dependencies_vk.is_empty() {
1465                 ptr::null()
1466             } else {
1467                 dependencies_vk.as_ptr()
1468             },
1469             ..Default::default()
1470         };
1471 
1472         if let Some(input_attachment_aspect_create_info) =
1473             input_attachment_aspect_create_info.as_mut()
1474         {
1475             input_attachment_aspect_create_info.p_next = create_info.p_next;
1476             create_info.p_next = input_attachment_aspect_create_info as *const _ as *const _;
1477         }
1478 
1479         if let Some(multiview_create_info) = multiview_create_info.as_mut() {
1480             multiview_create_info.p_next = create_info.p_next;
1481             create_info.p_next = multiview_create_info as *const _ as *const _;
1482         }
1483 
1484         Ok({
1485             let fns = device.fns();
1486             let mut output = MaybeUninit::uninit();
1487             (fns.v1_0.create_render_pass)(
1488                 device.handle(),
1489                 &create_info,
1490                 ptr::null(),
1491                 output.as_mut_ptr(),
1492             )
1493             .result()
1494             .map_err(VulkanError::from)?;
1495             output.assume_init()
1496         })
1497     }
1498 }
1499 
1500 /// Error that can happen when creating a `RenderPass`.
1501 #[derive(Clone, Debug, PartialEq, Eq)]
1502 pub enum RenderPassCreationError {
1503     /// Not enough memory.
1504     OomError(OomError),
1505 
1506     RequirementNotMet {
1507         required_for: &'static str,
1508         requires_one_of: RequiresOneOf,
1509     },
1510 
1511     /// An attachment is first used in the render pass with a read-only layout or as an input
1512     /// attachment, but its `load_op` or `stencil_load_op` is [`LoadOp::Clear`].
1513     AttachmentFirstUseLoadOpInvalid {
1514         attachment: u32,
1515         first_use_subpass: u32,
1516     },
1517 
1518     /// An attachment has an `initial_layout` or `final_layout` value that is invalid for the
1519     /// provided `format`.
1520     AttachmentLayoutInvalid { attachment: u32 },
1521 
1522     /// Correlated view masks were included, but multiview is not enabled on the render pass.
1523     CorrelatedViewMasksMultiviewNotEnabled,
1524 
1525     /// The provided correlated view masks contain a bit that is set in more than one element.
1526     CorrelatedViewMasksOverlapping,
1527 
1528     /// A subpass dependency specified an access type that was not supported by the given stages.
1529     DependencyAccessNotSupportedByStages { dependency: u32 },
1530 
1531     /// A subpass dependency has both `src_subpass` and `dst_subpass` set to `None`.
1532     DependencyBothSubpassesExternal { dependency: u32 },
1533 
1534     /// A subpass dependency specifies a subpass self-dependency and includes framebuffer stages in
1535     /// both `src_stages` and `dst_stages`, but the `by_region` dependency was not enabled.
1536     DependencySelfDependencyFramebufferStagesWithoutByRegion { dependency: u32 },
1537 
1538     /// A subpass dependency specifies a subpass self-dependency and includes
1539     /// non-framebuffer stages, but the latest stage in `src_stages` is after the earliest stage
1540     /// in `dst_stages`.
1541     DependencySelfDependencySourceStageAfterDestinationStage { dependency: u32 },
1542 
1543     /// A subpass dependency specifies a subpass self-dependency and has the `view_local` dependency
1544     /// enabled, but the inner offset value was not 0.
1545     DependencySelfDependencyViewLocalNonzeroViewOffset { dependency: u32 },
1546 
1547     /// A subpass dependency specifies a subpass self-dependency without the `view_local`
1548     /// dependency, but the referenced subpass has more than one bit set in its `view_mask`.
1549     DependencySelfDependencyViewMaskMultiple { dependency: u32, subpass: u32 },
1550 
1551     /// A subpass dependency has a `src_subpass` that is later than the `dst_subpass`.
1552     DependencySourceSubpassAfterDestinationSubpass { dependency: u32 },
1553 
1554     /// A subpass dependency has a bit set in the `src_stages` or `dst_stages` that is
1555     /// not supported for graphics pipelines.
1556     DependencyStageNotSupported { dependency: u32 },
1557 
1558     /// A subpass index in a subpass dependency is not less than the number of subpasses in the
1559     /// render pass.
1560     DependencySubpassOutOfRange { dependency: u32, subpass: u32 },
1561 
1562     /// In a subpass dependency, `dependency_flags` contains [`VIEW_LOCAL`], but `src_subpass` or
1563     /// `dst_subpass` were set to `None`.
1564     ///
1565     /// [`VIEW_LOCAL`]: crate::sync::DependencyFlags::VIEW_LOCAL
1566     DependencyViewLocalExternalDependency { dependency: u32 },
1567 
1568     /// In a subpass dependency, `dependency_flags` contains [`VIEW_LOCAL`], but multiview is not
1569     /// enabled on the render pass.
1570     ///
1571     /// [`VIEW_LOCAL`]: crate::sync::DependencyFlags::VIEW_LOCAL
1572     DependencyViewLocalMultiviewNotEnabled { dependency: u32 },
1573 
1574     /// In a subpass dependency, `view_offset` is not zero, but `dependency_flags` does not contain
1575     /// [`VIEW_LOCAL`].
1576     ///
1577     /// [`VIEW_LOCAL`]: crate::sync::DependencyFlags::VIEW_LOCAL
1578     DependencyViewOffzetNonzeroWithoutViewLocal { dependency: u32 },
1579 
1580     /// A reference to an attachment used other than as an input attachment in a subpass has
1581     /// one or more aspects selected.
1582     SubpassAttachmentAspectsNotEmpty { subpass: u32, attachment: u32 },
1583 
1584     /// An attachment used as an attachment in a subpass has a layout that is not supported for
1585     /// that usage.
1586     SubpassAttachmentLayoutInvalid {
1587         subpass: u32,
1588         attachment: u32,
1589         usage: &'static str,
1590     },
1591 
1592     /// The layouts of all uses of an attachment in a subpass do not match.
1593     SubpassAttachmentLayoutMismatch { subpass: u32, attachment: u32 },
1594 
1595     /// An attachment index in a subpass is not less than the number of attachments in the render
1596     /// pass.
1597     SubpassAttachmentOutOfRange { subpass: u32, attachment: u32 },
1598 
1599     /// An attachment is used as both a color attachment and a depth/stencil attachment in a
1600     /// subpass.
1601     SubpassAttachmentUsageColorDepthStencil { subpass: u32, attachment: u32 },
1602 
1603     /// An attachment used as an attachment in a subpass has a format that does not support that
1604     /// usage.
1605     SubpassAttachmentFormatUsageNotSupported {
1606         subpass: u32,
1607         attachment: u32,
1608         usage: &'static str,
1609     },
1610 
1611     /// An attachment used as a color attachment in a subpass with resolve attachments has a
1612     /// `samples` value of [`SampleCount::Sample1`].
1613     SubpassColorAttachmentWithResolveNotMultisampled { subpass: u32, attachment: u32 },
1614 
1615     /// An attachment used as a color or depth/stencil attachment in a subpass has a `samples` value
1616     /// that is different from the first color attachment.
1617     SubpassColorDepthStencilAttachmentSamplesMismatch {
1618         subpass: u32,
1619         attachment: u32,
1620         samples: SampleCount,
1621         first_samples: SampleCount,
1622     },
1623 
1624     /// A reference to an attachment used as an input attachment in a subpass selects aspects that
1625     /// are not present in the format of the attachment.
1626     SubpassInputAttachmentAspectsNotCompatible { subpass: u32, attachment: u32 },
1627 
1628     /// The `max_color_attachments` limit has been exceeded for a subpass.
1629     SubpassMaxColorAttachmentsExceeded {
1630         subpass: u32,
1631         color_attachment_count: u32,
1632         max: u32,
1633     },
1634 
1635     /// The `max_multiview_view_count` limit has been exceeded for a subpass.
1636     SubpassMaxMultiviewViewCountExceeded {
1637         subpass: u32,
1638         view_count: u32,
1639         max: u32,
1640     },
1641 
1642     /// The multiview state (whether `view_mask` is nonzero) of a subpass is different from the
1643     /// first subpass.
1644     SubpassMultiviewMismatch {
1645         subpass: u32,
1646         multiview: bool,
1647         first_subpass_multiview: bool,
1648     },
1649 
1650     /// An attachment marked as a preserve attachment in a subpass is also used as an attachment
1651     /// in that subpass.
1652     SubpassPreserveAttachmentUsedElsewhere { subpass: u32, attachment: u32 },
1653 
1654     /// The `resolve_attachments` field of a subpass was not empty, but its length did not match
1655     /// the length of `color_attachments`.
1656     SubpassResolveAttachmentsColorAttachmentsLenMismatch { subpass: u32 },
1657 
1658     /// An attachment used as a resolve attachment in a subpass has a `format` value different from
1659     /// the corresponding color attachment.
1660     SubpassResolveAttachmentFormatMismatch {
1661         subpass: u32,
1662         resolve_attachment: u32,
1663         color_attachment: u32,
1664     },
1665 
1666     /// An attachment used as a resolve attachment in a subpass has a `samples` value other than
1667     /// [`SampleCount::Sample1`].
1668     SubpassResolveAttachmentMultisampled { subpass: u32, attachment: u32 },
1669 
1670     /// A resolve attachment in a subpass is `Some`, but the corresponding color attachment is
1671     /// `None`.
1672     SubpassResolveAttachmentWithoutColorAttachment { subpass: u32 },
1673 }
1674 
1675 impl Error for RenderPassCreationError {
source(&self) -> Option<&(dyn Error + 'static)>1676     fn source(&self) -> Option<&(dyn Error + 'static)> {
1677         match self {
1678             RenderPassCreationError::OomError(err) => Some(err),
1679             _ => None,
1680         }
1681     }
1682 }
1683 
1684 impl Display for RenderPassCreationError {
fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError>1685     fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
1686         match self {
1687             Self::OomError(_) => write!(f, "not enough memory available"),
1688             Self::RequirementNotMet {
1689                 required_for,
1690                 requires_one_of,
1691             } => write!(
1692                 f,
1693                 "a requirement was not met for: {}; requires one of: {}",
1694                 required_for, requires_one_of,
1695             ),
1696             Self::AttachmentFirstUseLoadOpInvalid {
1697                 attachment,
1698                 first_use_subpass,
1699             } => write!(
1700                 f,
1701                 "attachment {} is first used in the render pass in subpass {} with a read-only \
1702                 layout or as an input attachment, but its `load_op` or `stencil_load_op` is \
1703                 `LoadOp::Clear`",
1704                 attachment, first_use_subpass,
1705             ),
1706             Self::AttachmentLayoutInvalid { attachment } => write!(
1707                 f,
1708                 "attachment {} has an `initial_layout` or `final_layout` value that is invalid for \
1709                 the provided `format`",
1710                 attachment,
1711             ),
1712             Self::CorrelatedViewMasksMultiviewNotEnabled => write!(
1713                 f,
1714                 "correlated view masks were included, but multiview is not enabled on the render \
1715                 pass",
1716             ),
1717             Self::CorrelatedViewMasksOverlapping => write!(
1718                 f,
1719                 "the provided correlated view masks contain a bit that is set in more than one \
1720                 element",
1721             ),
1722             Self::DependencyAccessNotSupportedByStages { dependency } => write!(
1723                 f,
1724                 "subpass dependency {} specified an access type that was not supported by the \
1725                 given stages",
1726                 dependency,
1727             ),
1728             Self::DependencySelfDependencyFramebufferStagesWithoutByRegion { dependency } => {
1729                 write!(
1730                     f,
1731                     "subpass dependency {} specifies a subpass self-dependency and includes \
1732                     framebuffer stages in both `src_stages` and `dst_stages`, but the \
1733                     `by_region` dependency was not enabled",
1734                     dependency,
1735                 )
1736             }
1737             Self::DependencySelfDependencySourceStageAfterDestinationStage { dependency } => {
1738                 write!(
1739                     f,
1740                     "subpass dependency {} specifies a subpass self-dependency and includes \
1741                     non-framebuffer stages, but the latest stage in `src_stages` is after the \
1742                     earliest stage in `dst_stages`",
1743                     dependency,
1744                 )
1745             }
1746             Self::DependencySelfDependencyViewLocalNonzeroViewOffset { dependency } => write!(
1747                 f,
1748                 "subpass dependency {} specifies a subpass self-dependency and has the \
1749                 `view_local` dependency enabled, but the inner offset value was not 0",
1750                 dependency,
1751             ),
1752             Self::DependencySelfDependencyViewMaskMultiple {
1753                 dependency,
1754                 subpass,
1755             } => write!(
1756                 f,
1757                 "subpass dependency {} specifies a subpass self-dependency without the \
1758                 `view_local` dependency, but the referenced subpass {} has more than one bit set \
1759                 in its `view_mask`",
1760                 dependency, subpass,
1761             ),
1762             Self::DependencySourceSubpassAfterDestinationSubpass { dependency } => write!(
1763                 f,
1764                 "subpass dependency {} has a `src_subpass` that is later than the \
1765                 `dst_subpass`",
1766                 dependency,
1767             ),
1768             Self::DependencyStageNotSupported { dependency } => write!(
1769                 f,
1770                 "subpass dependency {} has a bit set in the `src_stages` or \
1771                 `dst_stages` that is not supported for graphics pipelines",
1772                 dependency,
1773             ),
1774             Self::DependencyBothSubpassesExternal { dependency } => write!(
1775                 f,
1776                 "subpass dependency {} has both `src_subpass` and `dst_subpass` set to \
1777                 `None`",
1778                 dependency,
1779             ),
1780             Self::DependencySubpassOutOfRange {
1781                 dependency,
1782                 subpass,
1783             } => write!(
1784                 f,
1785                 "the subpass index {} in subpass dependency {} is not less than the number of \
1786                 subpasses in the render pass",
1787                 subpass, dependency,
1788             ),
1789             Self::DependencyViewLocalExternalDependency { dependency } => write!(
1790                 f,
1791                 "in subpass dependency {}, `dependency_flags` contains `VIEW_LOCAL`, but \
1792                 `src_subpass` or `dst_subpass` were set to `None`",
1793                 dependency,
1794             ),
1795             Self::DependencyViewLocalMultiviewNotEnabled { dependency } => write!(
1796                 f,
1797                 "in subpass dependency {}, `dependency_flags` contains `VIEW_LOCAL`, but \
1798                 multiview is not enabled on the render pass",
1799                 dependency,
1800             ),
1801             Self::DependencyViewOffzetNonzeroWithoutViewLocal { dependency } => write!(
1802                 f,
1803                 "in subpass dependency {}, `view_offset` is not zero, but `dependency_flags` does \
1804                 not contain `VIEW_LOCAL`",
1805                 dependency,
1806             ),
1807             Self::SubpassAttachmentAspectsNotEmpty {
1808                 subpass,
1809                 attachment,
1810             } => write!(
1811                 f,
1812                 "a reference to attachment {} used other than as an input attachment in subpass {} \
1813                 has one or more aspects selected",
1814                 attachment, subpass,
1815             ),
1816             Self::SubpassAttachmentLayoutMismatch {
1817                 subpass,
1818                 attachment,
1819             } => write!(
1820                 f,
1821                 "the layouts of all uses of attachment {} in subpass {} do not match.",
1822                 attachment, subpass,
1823             ),
1824             Self::SubpassAttachmentLayoutInvalid {
1825                 subpass,
1826                 attachment,
1827                 usage,
1828             } => write!(
1829                 f,
1830                 "attachment {} used as {} attachment in subpass {} has a layout that is not \
1831                 supported for that usage",
1832                 attachment, usage, subpass,
1833             ),
1834             Self::SubpassAttachmentOutOfRange {
1835                 subpass,
1836                 attachment,
1837             } => write!(
1838                 f,
1839                 "the attachment index {} in subpass {} is not less than the number of attachments \
1840                 in the render pass",
1841                 attachment, subpass,
1842             ),
1843             Self::SubpassAttachmentUsageColorDepthStencil {
1844                 subpass,
1845                 attachment,
1846             } => write!(
1847                 f,
1848                 "attachment {} is used as both a color attachment and a depth/stencil attachment \
1849                 in subpass {}",
1850                 attachment, subpass,
1851             ),
1852             Self::SubpassAttachmentFormatUsageNotSupported {
1853                 subpass,
1854                 attachment,
1855                 usage,
1856             } => write!(
1857                 f,
1858                 "attachment {} used as {} attachment in subpass {} has a format that does not \
1859                 support that usage",
1860                 attachment, usage, subpass,
1861             ),
1862             Self::SubpassColorAttachmentWithResolveNotMultisampled {
1863                 subpass,
1864                 attachment,
1865             } => write!(
1866                 f,
1867                 "attachment {} used as a color attachment in subpass {} with resolve attachments \
1868                 has a `samples` value of `SampleCount::Sample1`",
1869                 attachment, subpass,
1870             ),
1871             Self::SubpassColorDepthStencilAttachmentSamplesMismatch {
1872                 subpass,
1873                 attachment,
1874                 samples,
1875                 first_samples,
1876             } => write!(
1877                 f,
1878                 "attachment {} used as a color or depth/stencil attachment in subpass {} has a \
1879                 `samples` value {:?} that is different from the first color attachment ({:?})",
1880                 attachment, subpass, samples, first_samples,
1881             ),
1882             Self::SubpassInputAttachmentAspectsNotCompatible {
1883                 subpass,
1884                 attachment,
1885             } => write!(
1886                 f,
1887                 "a reference to attachment {} used as an input attachment in subpass {} selects \
1888                 aspects that are not present in the format of the attachment",
1889                 attachment, subpass,
1890             ),
1891             Self::SubpassMaxColorAttachmentsExceeded { .. } => {
1892                 write!(f, "the `max_color_attachments` limit has been exceeded")
1893             }
1894             Self::SubpassMaxMultiviewViewCountExceeded { .. } => write!(
1895                 f,
1896                 "the `max_multiview_view_count` limit has been exceeded for a subpass",
1897             ),
1898             Self::SubpassMultiviewMismatch {
1899                 subpass,
1900                 multiview,
1901                 first_subpass_multiview,
1902             } => write!(
1903                 f,
1904                 "the multiview state (whether `view_mask` is nonzero) of subpass {} is {}, which \
1905                 is different from the first subpass ({})",
1906                 subpass, multiview, first_subpass_multiview,
1907             ),
1908             Self::SubpassPreserveAttachmentUsedElsewhere {
1909                 subpass,
1910                 attachment,
1911             } => write!(
1912                 f,
1913                 "attachment {} marked as a preserve attachment in subpass {} is also used as an \
1914                 attachment in that subpass",
1915                 attachment, subpass,
1916             ),
1917             Self::SubpassResolveAttachmentsColorAttachmentsLenMismatch { subpass } => write!(
1918                 f,
1919                 "the `resolve_attachments` field of subpass {} was not empty, but its length did \
1920                 not match the length of `color_attachments`",
1921                 subpass,
1922             ),
1923             Self::SubpassResolveAttachmentFormatMismatch {
1924                 subpass,
1925                 resolve_attachment,
1926                 color_attachment,
1927             } => write!(
1928                 f,
1929                 "attachment {} used as a resolve attachment in subpass {} has a `format` value \
1930                 different from the corresponding color attachment {}",
1931                 subpass, resolve_attachment, color_attachment,
1932             ),
1933             Self::SubpassResolveAttachmentMultisampled {
1934                 subpass,
1935                 attachment,
1936             } => write!(
1937                 f,
1938                 "attachment {} used as a resolve attachment in subpass {} has a `samples` value \
1939                 other than `SampleCount::Sample1`",
1940                 attachment, subpass,
1941             ),
1942             Self::SubpassResolveAttachmentWithoutColorAttachment { subpass } => write!(
1943                 f,
1944                 "a resolve attachment in subpass {} is `Some`, but the corresponding color \
1945                 attachment is `None`",
1946                 subpass,
1947             ),
1948         }
1949     }
1950 }
1951 
1952 impl From<OomError> for RenderPassCreationError {
from(err: OomError) -> RenderPassCreationError1953     fn from(err: OomError) -> RenderPassCreationError {
1954         RenderPassCreationError::OomError(err)
1955     }
1956 }
1957 
1958 impl From<VulkanError> for RenderPassCreationError {
from(err: VulkanError) -> RenderPassCreationError1959     fn from(err: VulkanError) -> RenderPassCreationError {
1960         match err {
1961             err @ VulkanError::OutOfHostMemory => {
1962                 RenderPassCreationError::OomError(OomError::from(err))
1963             }
1964             err @ VulkanError::OutOfDeviceMemory => {
1965                 RenderPassCreationError::OomError(OomError::from(err))
1966             }
1967             _ => panic!("unexpected error: {:?}", err),
1968         }
1969     }
1970 }
1971 
1972 impl From<RequirementNotMet> for RenderPassCreationError {
from(err: RequirementNotMet) -> Self1973     fn from(err: RequirementNotMet) -> Self {
1974         Self::RequirementNotMet {
1975             required_for: err.required_for,
1976             requires_one_of: err.requires_one_of,
1977         }
1978     }
1979 }
1980