1 // Copyright (c) 2016 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 //! Description of the steps of the rendering process, and the images used as input or output.
11 //!
12 //! # Render passes and framebuffers
13 //!
14 //! There are two concepts in Vulkan:
15 //!
16 //! - A *render pass* describes the overall process of drawing a frame. It is subdivided into one
17 //!   or more subpasses.
18 //! - A *framebuffer* contains the list of image views that are attached during the drawing of
19 //!   each subpass.
20 //!
21 //! Render passes are typically created at initialization only (for example during a loading
22 //! screen) because they can be costly, while framebuffers can be created and destroyed either at
23 //! initialization or during the frame.
24 //!
25 //! Consequently you can create graphics pipelines from a render pass object alone.
26 //! A `Framebuffer` object is only needed when you actually add draw commands to a command buffer.
27 
28 pub use self::{
29     create::RenderPassCreationError,
30     framebuffer::{Framebuffer, FramebufferCreateInfo, FramebufferCreationError},
31 };
32 use crate::{
33     device::{Device, DeviceOwned},
34     format::Format,
35     image::{ImageAspects, ImageLayout, SampleCount},
36     macros::{impl_id_counter, vulkan_bitflags_enum, vulkan_enum},
37     shader::ShaderInterface,
38     sync::{AccessFlags, DependencyFlags, PipelineStages},
39     Version, VulkanObject,
40 };
41 use std::{cmp::max, mem::MaybeUninit, num::NonZeroU64, ptr, sync::Arc};
42 
43 #[macro_use]
44 mod macros;
45 mod create;
46 mod framebuffer;
47 
48 /// An object representing the discrete steps in which rendering is done.
49 ///
50 /// A render pass in Vulkan is made up of three parts:
51 /// - A list of attachments, which are image views that are inputs, outputs or intermediate stages
52 ///   in the rendering process.
53 /// - One or more subpasses, which are the steps in which the rendering process, takes place,
54 ///   and the attachments that are used for each step.
55 /// - Dependencies, which describe how the input and output data of each subpass is to be passed
56 ///   from one subpass to the next.
57 ///
58 /// ```
59 /// use vulkano::render_pass::{RenderPass, RenderPassCreateInfo, SubpassDescription};
60 ///
61 /// # let device: std::sync::Arc<vulkano::device::Device> = return;
62 /// let render_pass = RenderPass::new(
63 ///     device.clone(),
64 ///     RenderPassCreateInfo {
65 ///         subpasses: vec![SubpassDescription::default()],
66 ///         ..Default::default()
67 ///     },
68 /// ).unwrap();
69 /// ```
70 ///
71 /// This example creates a render pass with no attachment and one single subpass that doesn't draw
72 /// on anything. While it's sometimes useful, most of the time it's not what you want.
73 ///
74 /// The easiest way to create a "real" render pass is to use the `single_pass_renderpass!` macro.
75 ///
76 /// ```
77 /// # #[macro_use] extern crate vulkano;
78 /// # fn main() {
79 /// # let device: std::sync::Arc<vulkano::device::Device> = return;
80 /// use vulkano::format::Format;
81 ///
82 /// let render_pass = single_pass_renderpass!(
83 ///     device.clone(),
84 ///     attachments: {
85 ///         // `foo` is a custom name we give to the first and only attachment.
86 ///         foo: {
87 ///             load: Clear,
88 ///             store: Store,
89 ///             format: Format::R8G8B8A8_UNORM,
90 ///             samples: 1,
91 ///         },
92 ///     },
93 ///     pass: {
94 ///         color: [foo],       // Repeat the attachment name here.
95 ///         depth_stencil: {},
96 ///     },
97 /// )
98 /// .unwrap();
99 /// # }
100 /// ```
101 ///
102 /// See the documentation of the macro for more details. TODO: put link here
103 #[derive(Debug)]
104 pub struct RenderPass {
105     handle: ash::vk::RenderPass,
106     device: Arc<Device>,
107     id: NonZeroU64,
108 
109     attachments: Vec<AttachmentDescription>,
110     subpasses: Vec<SubpassDescription>,
111     dependencies: Vec<SubpassDependency>,
112     correlated_view_masks: Vec<u32>,
113 
114     attachment_uses: Vec<Option<AttachmentUse>>,
115     granularity: [u32; 2],
116     views_used: u32,
117 }
118 
119 impl RenderPass {
120     /// Creates a new `RenderPass`.
121     ///
122     /// # Panics
123     ///
124     /// - Panics if `create_info.subpasses` is empty.
125     /// - Panics if any element of `create_info.attachments` has a `format` of `None`.
new( device: Arc<Device>, mut create_info: RenderPassCreateInfo, ) -> Result<Arc<RenderPass>, RenderPassCreationError>126     pub fn new(
127         device: Arc<Device>,
128         mut create_info: RenderPassCreateInfo,
129     ) -> Result<Arc<RenderPass>, RenderPassCreationError> {
130         Self::validate(&device, &mut create_info)?;
131 
132         let handle = unsafe {
133             if device.api_version() >= Version::V1_2
134                 || device.enabled_extensions().khr_create_renderpass2
135             {
136                 Self::create_v2(&device, &create_info)?
137             } else {
138                 Self::create_v1(&device, &create_info)?
139             }
140         };
141 
142         unsafe { Ok(Self::from_handle(device, handle, create_info)) }
143     }
144 
145     /// Builds a render pass with one subpass and no attachment.
146     ///
147     /// This method is useful for quick tests.
148     #[inline]
empty_single_pass( device: Arc<Device>, ) -> Result<Arc<RenderPass>, RenderPassCreationError>149     pub fn empty_single_pass(
150         device: Arc<Device>,
151     ) -> Result<Arc<RenderPass>, RenderPassCreationError> {
152         RenderPass::new(
153             device,
154             RenderPassCreateInfo {
155                 subpasses: vec![SubpassDescription::default()],
156                 ..Default::default()
157             },
158         )
159     }
160 
161     /// Creates a new `RenderPass` from a raw object handle.
162     ///
163     /// # Safety
164     ///
165     /// - `handle` must be a valid Vulkan object handle created from `device`.
166     /// - `create_info` must match the info used to create the object.
167     #[inline]
from_handle( device: Arc<Device>, handle: ash::vk::RenderPass, create_info: RenderPassCreateInfo, ) -> Arc<RenderPass>168     pub unsafe fn from_handle(
169         device: Arc<Device>,
170         handle: ash::vk::RenderPass,
171         create_info: RenderPassCreateInfo,
172     ) -> Arc<RenderPass> {
173         let RenderPassCreateInfo {
174             attachments,
175             subpasses,
176             dependencies,
177             correlated_view_masks,
178             _ne: _,
179         } = create_info;
180 
181         let granularity = Self::get_granularity(&device, handle);
182         let mut attachment_uses: Vec<Option<AttachmentUse>> = vec![None; attachments.len()];
183         let mut views_used = 0;
184 
185         for (index, subpass_desc) in subpasses.iter().enumerate() {
186             let index = index as u32;
187             let &SubpassDescription {
188                 view_mask,
189                 ref input_attachments,
190                 ref color_attachments,
191                 ref resolve_attachments,
192                 ref depth_stencil_attachment,
193                 ..
194             } = subpass_desc;
195 
196             for atch_ref in (input_attachments.iter().flatten())
197                 .chain(color_attachments.iter().flatten())
198                 .chain(resolve_attachments.iter().flatten())
199                 .chain(depth_stencil_attachment.iter())
200             {
201                 match &mut attachment_uses[atch_ref.attachment as usize] {
202                     Some(attachment_use) => attachment_use.last_use_subpass = index,
203                     attachment_use @ None => {
204                         *attachment_use = Some(AttachmentUse {
205                             first_use_subpass: index,
206                             last_use_subpass: index,
207                         })
208                     }
209                 }
210             }
211 
212             views_used = max(views_used, u32::BITS - view_mask.leading_zeros());
213         }
214 
215         Arc::new(RenderPass {
216             handle,
217             device,
218             id: Self::next_id(),
219 
220             attachments,
221             subpasses,
222             dependencies,
223             correlated_view_masks,
224 
225             attachment_uses,
226             granularity,
227             views_used,
228         })
229     }
230 
get_granularity(device: &Arc<Device>, handle: ash::vk::RenderPass) -> [u32; 2]231     unsafe fn get_granularity(device: &Arc<Device>, handle: ash::vk::RenderPass) -> [u32; 2] {
232         let fns = device.fns();
233         let mut out = MaybeUninit::uninit();
234         (fns.v1_0.get_render_area_granularity)(device.handle(), handle, out.as_mut_ptr());
235 
236         let out = out.assume_init();
237         debug_assert_ne!(out.width, 0);
238         debug_assert_ne!(out.height, 0);
239         [out.width, out.height]
240     }
241 
242     /// Returns the attachments of the render pass.
243     #[inline]
attachments(&self) -> &[AttachmentDescription]244     pub fn attachments(&self) -> &[AttachmentDescription] {
245         &self.attachments
246     }
247 
248     /// Returns the subpasses of the render pass.
249     #[inline]
subpasses(&self) -> &[SubpassDescription]250     pub fn subpasses(&self) -> &[SubpassDescription] {
251         &self.subpasses
252     }
253 
254     /// Returns the dependencies of the render pass.
255     #[inline]
dependencies(&self) -> &[SubpassDependency]256     pub fn dependencies(&self) -> &[SubpassDependency] {
257         &self.dependencies
258     }
259 
260     /// Returns the correlated view masks of the render pass.
261     #[inline]
correlated_view_masks(&self) -> &[u32]262     pub fn correlated_view_masks(&self) -> &[u32] {
263         &self.correlated_view_masks
264     }
265 
266     /// If the render pass has multiview enabled, returns the number of views used by the render
267     /// pass. Returns 0 if multiview is not enabled.
268     #[inline]
views_used(&self) -> u32269     pub fn views_used(&self) -> u32 {
270         self.views_used
271     }
272 
273     /// Returns the granularity of this render pass.
274     ///
275     /// If the render area of a render pass in a command buffer is a multiple of this granularity,
276     /// then the performance will be optimal. Performances are always optimal for render areas
277     /// that cover the whole framebuffer.
278     #[inline]
granularity(&self) -> [u32; 2]279     pub fn granularity(&self) -> [u32; 2] {
280         self.granularity
281     }
282 
283     /// Returns the first subpass of the render pass.
284     #[inline]
first_subpass(self: Arc<Self>) -> Subpass285     pub fn first_subpass(self: Arc<Self>) -> Subpass {
286         Subpass {
287             render_pass: self,
288             subpass_id: 0, // Guaranteed to exist
289         }
290     }
291 
292     /// Returns `true` if this render pass is compatible with the other render pass,
293     /// as defined in the [`Render Pass Compatibility` section of the Vulkan specs](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap8.html#renderpass-compatibility).
is_compatible_with(&self, other: &RenderPass) -> bool294     pub fn is_compatible_with(&self, other: &RenderPass) -> bool {
295         if self == other {
296             return true;
297         }
298 
299         let Self {
300             handle: _,
301             device: _,
302             id: _,
303             attachments: attachments1,
304             subpasses: subpasses1,
305             dependencies: dependencies1,
306             correlated_view_masks: correlated_view_masks1,
307             attachment_uses: _,
308             granularity: _,
309             views_used: _,
310         } = self;
311         let Self {
312             handle: _,
313             device: _,
314             id: _,
315             attachments: attachments2,
316             subpasses: subpasses2,
317             dependencies: dependencies2,
318             attachment_uses: _,
319             correlated_view_masks: correlated_view_masks2,
320             granularity: _,
321             views_used: _,
322         } = other;
323 
324         if attachments1.len() != attachments2.len() {
325             return false;
326         }
327 
328         if !attachments1
329             .iter()
330             .zip(attachments2)
331             .all(|(attachment_desc1, attachment_desc2)| {
332                 let AttachmentDescription {
333                     format: format1,
334                     samples: samples1,
335                     load_op: _,
336                     store_op: _,
337                     stencil_load_op: _,
338                     stencil_store_op: _,
339                     initial_layout: _,
340                     final_layout: _,
341                     _ne: _,
342                 } = attachment_desc1;
343                 let AttachmentDescription {
344                     format: format2,
345                     samples: samples2,
346                     load_op: _,
347                     store_op: _,
348                     stencil_load_op: _,
349                     stencil_store_op: _,
350                     initial_layout: _,
351                     final_layout: _,
352                     _ne: _,
353                 } = attachment_desc2;
354 
355                 format1 == format2 && samples1 == samples2
356             })
357         {
358             return false;
359         }
360 
361         let are_atch_refs_compatible = |atch_ref1, atch_ref2| match (atch_ref1, atch_ref2) {
362             (None, None) => true,
363             (Some(atch_ref1), Some(atch_ref2)) => {
364                 let &AttachmentReference {
365                     attachment: attachment1,
366                     layout: _,
367                     aspects: aspects1,
368                     _ne: _,
369                 } = atch_ref1;
370                 let AttachmentDescription {
371                     format: format1,
372                     samples: samples1,
373                     load_op: _,
374                     store_op: _,
375                     stencil_load_op: _,
376                     stencil_store_op: _,
377                     initial_layout: _,
378                     final_layout: _,
379                     _ne: _,
380                 } = &attachments1[attachment1 as usize];
381 
382                 let &AttachmentReference {
383                     attachment: attachment2,
384                     layout: _,
385                     aspects: aspects2,
386                     _ne: _,
387                 } = atch_ref2;
388                 let AttachmentDescription {
389                     format: format2,
390                     samples: samples2,
391                     load_op: _,
392                     store_op: _,
393                     stencil_load_op: _,
394                     stencil_store_op: _,
395                     initial_layout: _,
396                     final_layout: _,
397                     _ne: _,
398                 } = &attachments2[attachment2 as usize];
399 
400                 format1 == format2 && samples1 == samples2 && aspects1 == aspects2
401             }
402             _ => false,
403         };
404 
405         if subpasses1.len() != subpasses2.len() {
406             return false;
407         }
408 
409         if !(subpasses1.iter())
410             .zip(subpasses2.iter())
411             .all(|(subpass1, subpass2)| {
412                 let SubpassDescription {
413                     view_mask: view_mask1,
414                     input_attachments: input_attachments1,
415                     color_attachments: color_attachments1,
416                     resolve_attachments: resolve_attachments1,
417                     depth_stencil_attachment: depth_stencil_attachment1,
418                     preserve_attachments: _,
419                     _ne: _,
420                 } = subpass1;
421                 let SubpassDescription {
422                     view_mask: view_mask2,
423                     input_attachments: input_attachments2,
424                     color_attachments: color_attachments2,
425                     resolve_attachments: resolve_attachments2,
426                     depth_stencil_attachment: depth_stencil_attachment2,
427                     preserve_attachments: _,
428                     _ne: _,
429                 } = subpass2;
430 
431                 if !(0..max(input_attachments1.len(), input_attachments2.len())).all(|i| {
432                     are_atch_refs_compatible(
433                         input_attachments1.get(i).and_then(|x| x.as_ref()),
434                         input_attachments2.get(i).and_then(|x| x.as_ref()),
435                     )
436                 }) {
437                     return false;
438                 }
439 
440                 if !(0..max(color_attachments1.len(), color_attachments2.len())).all(|i| {
441                     are_atch_refs_compatible(
442                         color_attachments1.get(i).and_then(|x| x.as_ref()),
443                         color_attachments2.get(i).and_then(|x| x.as_ref()),
444                     )
445                 }) {
446                     return false;
447                 }
448 
449                 if subpasses1.len() > 1
450                     && !(0..max(resolve_attachments1.len(), resolve_attachments2.len())).all(|i| {
451                         are_atch_refs_compatible(
452                             resolve_attachments1.get(i).and_then(|x| x.as_ref()),
453                             resolve_attachments2.get(i).and_then(|x| x.as_ref()),
454                         )
455                     })
456                 {
457                     return false;
458                 }
459 
460                 if !are_atch_refs_compatible(
461                     depth_stencil_attachment1.as_ref(),
462                     depth_stencil_attachment2.as_ref(),
463                 ) {
464                     return false;
465                 }
466 
467                 if view_mask1 != view_mask2 {
468                     return false;
469                 }
470 
471                 true
472             })
473         {
474             return false;
475         }
476 
477         if dependencies1 != dependencies2 {
478             return false;
479         }
480 
481         if correlated_view_masks1 != correlated_view_masks2 {
482             return false;
483         }
484 
485         true
486     }
487 
488     /// Returns `true` if the subpass of this description is compatible with the shader's fragment
489     /// output definition.
is_compatible_with_shader( &self, subpass: u32, shader_interface: &ShaderInterface, ) -> bool490     pub fn is_compatible_with_shader(
491         &self,
492         subpass: u32,
493         shader_interface: &ShaderInterface,
494     ) -> bool {
495         let subpass_descr = match self.subpasses.get(subpass as usize) {
496             Some(s) => s,
497             None => return false,
498         };
499 
500         for element in shader_interface.elements() {
501             assert!(!element.ty.is_64bit); // TODO: implement
502             let location_range = element.location..element.location + element.ty.num_locations();
503 
504             for location in location_range {
505                 let attachment_id = match subpass_descr.color_attachments.get(location as usize) {
506                     Some(Some(atch_ref)) => atch_ref.attachment,
507                     _ => return false,
508                 };
509 
510                 let _attachment_desc = &self.attachments[attachment_id as usize];
511 
512                 // FIXME: compare formats depending on the number of components and data type
513                 /*if attachment_desc.format != element.format {
514                     return false;
515                 }*/
516             }
517         }
518 
519         true
520     }
521 }
522 
523 impl Drop for RenderPass {
524     #[inline]
drop(&mut self)525     fn drop(&mut self) {
526         unsafe {
527             let fns = self.device.fns();
528             (fns.v1_0.destroy_render_pass)(self.device.handle(), self.handle, ptr::null());
529         }
530     }
531 }
532 
533 unsafe impl VulkanObject for RenderPass {
534     type Handle = ash::vk::RenderPass;
535 
536     #[inline]
handle(&self) -> Self::Handle537     fn handle(&self) -> Self::Handle {
538         self.handle
539     }
540 }
541 
542 unsafe impl DeviceOwned for RenderPass {
543     #[inline]
device(&self) -> &Arc<Device>544     fn device(&self) -> &Arc<Device> {
545         &self.device
546     }
547 }
548 
549 impl_id_counter!(RenderPass);
550 
551 /// Represents a subpass within a `RenderPass` object.
552 ///
553 /// This struct doesn't correspond to anything in Vulkan. It is simply an equivalent to a
554 /// tuple of a render pass and subpass index. Contrary to a tuple, however, the existence of the
555 /// subpass is checked when the object is created. When you have a `Subpass` you are guaranteed
556 /// that the given subpass does exist.
557 #[derive(Debug, Clone)]
558 pub struct Subpass {
559     render_pass: Arc<RenderPass>,
560     subpass_id: u32,
561 }
562 
563 impl Subpass {
564     /// Returns a handle that represents a subpass of a render pass.
565     #[inline]
from(render_pass: Arc<RenderPass>, id: u32) -> Option<Subpass>566     pub fn from(render_pass: Arc<RenderPass>, id: u32) -> Option<Subpass> {
567         if (id as usize) < render_pass.subpasses().len() {
568             Some(Subpass {
569                 render_pass,
570                 subpass_id: id,
571             })
572         } else {
573             None
574         }
575     }
576 
577     /// Returns the render pass of this subpass.
578     #[inline]
render_pass(&self) -> &Arc<RenderPass>579     pub fn render_pass(&self) -> &Arc<RenderPass> {
580         &self.render_pass
581     }
582 
583     /// Returns the index of this subpass within the renderpass.
584     #[inline]
index(&self) -> u32585     pub fn index(&self) -> u32 {
586         self.subpass_id
587     }
588 
589     /// Returns the subpass description for this subpass.
590     #[inline]
subpass_desc(&self) -> &SubpassDescription591     pub fn subpass_desc(&self) -> &SubpassDescription {
592         &self.render_pass.subpasses()[self.subpass_id as usize]
593     }
594 
595     /// Returns whether this subpass is the last one in the render pass. If `true` is returned,
596     /// calling `next_subpass` will panic.
597     #[inline]
is_last_subpass(&self) -> bool598     pub fn is_last_subpass(&self) -> bool {
599         self.subpass_id as usize == self.render_pass.subpasses().len() - 1
600     }
601 
602     /// Advances to the next subpass after this one.
603     ///
604     /// # Panics
605     ///
606     /// - Panics if there are no more render passes.
607     #[inline]
next_subpass(&mut self)608     pub fn next_subpass(&mut self) {
609         let next_id = self.subpass_id + 1;
610         assert!((next_id as usize) < self.render_pass.subpasses().len());
611         self.subpass_id = next_id;
612     }
613 
614     #[inline]
attachment_desc(&self, atch_num: u32) -> &AttachmentDescription615     fn attachment_desc(&self, atch_num: u32) -> &AttachmentDescription {
616         &self.render_pass.attachments()[atch_num as usize]
617     }
618 
619     /// Returns the number of color attachments in this subpass.
620     #[inline]
num_color_attachments(&self) -> u32621     pub fn num_color_attachments(&self) -> u32 {
622         self.subpass_desc().color_attachments.len() as u32
623     }
624 
625     /// Returns true if the subpass has a depth attachment or a depth-stencil attachment.
626     #[inline]
has_depth(&self) -> bool627     pub fn has_depth(&self) -> bool {
628         let subpass_desc = self.subpass_desc();
629         let atch_num = match &subpass_desc.depth_stencil_attachment {
630             Some(atch_ref) => atch_ref.attachment,
631             None => return false,
632         };
633 
634         self.attachment_desc(atch_num)
635             .format
636             .map_or(false, |f| f.aspects().intersects(ImageAspects::DEPTH))
637     }
638 
639     /// Returns true if the subpass has a depth attachment or a depth-stencil attachment whose
640     /// layout does not have a read-only depth layout.
641     #[inline]
has_writable_depth(&self) -> bool642     pub fn has_writable_depth(&self) -> bool {
643         let subpass_desc = self.subpass_desc();
644         let atch_num = match &subpass_desc.depth_stencil_attachment {
645             Some(atch_ref) => {
646                 if matches!(
647                     atch_ref.layout,
648                     ImageLayout::DepthStencilReadOnlyOptimal
649                         | ImageLayout::DepthReadOnlyStencilAttachmentOptimal
650                 ) {
651                     return false;
652                 }
653                 atch_ref.attachment
654             }
655             None => return false,
656         };
657 
658         self.attachment_desc(atch_num)
659             .format
660             .map_or(false, |f| f.aspects().intersects(ImageAspects::DEPTH))
661     }
662 
663     /// Returns true if the subpass has a stencil attachment or a depth-stencil attachment.
664     #[inline]
has_stencil(&self) -> bool665     pub fn has_stencil(&self) -> bool {
666         let subpass_desc = self.subpass_desc();
667         let atch_num = match &subpass_desc.depth_stencil_attachment {
668             Some(atch_ref) => atch_ref.attachment,
669             None => return false,
670         };
671 
672         self.attachment_desc(atch_num)
673             .format
674             .map_or(false, |f| f.aspects().intersects(ImageAspects::STENCIL))
675     }
676 
677     /// Returns true if the subpass has a stencil attachment or a depth-stencil attachment whose
678     /// layout does not have a read-only stencil layout.
679     #[inline]
has_writable_stencil(&self) -> bool680     pub fn has_writable_stencil(&self) -> bool {
681         let subpass_desc = self.subpass_desc();
682 
683         let atch_num = match &subpass_desc.depth_stencil_attachment {
684             Some(atch_ref) => {
685                 if matches!(
686                     atch_ref.layout,
687                     ImageLayout::DepthStencilReadOnlyOptimal
688                         | ImageLayout::DepthAttachmentStencilReadOnlyOptimal
689                 ) {
690                     return false;
691                 }
692                 atch_ref.attachment
693             }
694             None => return false,
695         };
696 
697         self.attachment_desc(atch_num)
698             .format
699             .map_or(false, |f| f.aspects().intersects(ImageAspects::STENCIL))
700     }
701 
702     /// Returns the number of samples in the color and/or depth/stencil attachments. Returns `None`
703     /// if there is no such attachment in this subpass.
704     #[inline]
num_samples(&self) -> Option<SampleCount>705     pub fn num_samples(&self) -> Option<SampleCount> {
706         let subpass_desc = self.subpass_desc();
707 
708         // TODO: chain input attachments as well?
709         subpass_desc
710             .color_attachments
711             .iter()
712             .flatten()
713             .chain(subpass_desc.depth_stencil_attachment.iter())
714             .filter_map(|atch_ref| {
715                 self.render_pass
716                     .attachments()
717                     .get(atch_ref.attachment as usize)
718             })
719             .next()
720             .map(|atch_desc| atch_desc.samples)
721     }
722 
723     /// Returns `true` if this subpass is compatible with the fragment output definition.
724     // TODO: return proper error
725     #[inline]
is_compatible_with(&self, shader_interface: &ShaderInterface) -> bool726     pub fn is_compatible_with(&self, shader_interface: &ShaderInterface) -> bool {
727         self.render_pass
728             .is_compatible_with_shader(self.subpass_id, shader_interface)
729     }
730 
load_op(&self, attachment_index: u32) -> Option<LoadOp>731     pub(crate) fn load_op(&self, attachment_index: u32) -> Option<LoadOp> {
732         self.render_pass.attachment_uses[attachment_index as usize]
733             .as_ref()
734             .and_then(|attachment_use| {
735                 (attachment_use.first_use_subpass == self.subpass_id)
736                     .then(|| self.render_pass.attachments[attachment_index as usize].load_op)
737             })
738     }
739 
store_op(&self, attachment_index: u32) -> Option<StoreOp>740     pub(crate) fn store_op(&self, attachment_index: u32) -> Option<StoreOp> {
741         self.render_pass.attachment_uses[attachment_index as usize]
742             .as_ref()
743             .and_then(|attachment_use| {
744                 (attachment_use.last_use_subpass == self.subpass_id)
745                     .then(|| self.render_pass.attachments[attachment_index as usize].store_op)
746             })
747     }
748 
stencil_load_op(&self, attachment_index: u32) -> Option<LoadOp>749     pub(crate) fn stencil_load_op(&self, attachment_index: u32) -> Option<LoadOp> {
750         self.render_pass.attachment_uses[attachment_index as usize]
751             .as_ref()
752             .and_then(|attachment_use| {
753                 (attachment_use.first_use_subpass == self.subpass_id).then(|| {
754                     self.render_pass.attachments[attachment_index as usize].stencil_load_op
755                 })
756             })
757     }
758 
stencil_store_op(&self, attachment_index: u32) -> Option<StoreOp>759     pub(crate) fn stencil_store_op(&self, attachment_index: u32) -> Option<StoreOp> {
760         self.render_pass.attachment_uses[attachment_index as usize]
761             .as_ref()
762             .and_then(|attachment_use| {
763                 (attachment_use.last_use_subpass == self.subpass_id).then(|| {
764                     self.render_pass.attachments[attachment_index as usize].stencil_store_op
765                 })
766             })
767     }
768 }
769 
770 impl From<Subpass> for (Arc<RenderPass>, u32) {
771     #[inline]
from(value: Subpass) -> (Arc<RenderPass>, u32)772     fn from(value: Subpass) -> (Arc<RenderPass>, u32) {
773         (value.render_pass, value.subpass_id)
774     }
775 }
776 
777 /// Parameters to create a new `RenderPass`.
778 #[derive(Clone, Debug)]
779 pub struct RenderPassCreateInfo {
780     /// The attachments available for the render pass.
781     ///
782     /// The default value is empty.
783     pub attachments: Vec<AttachmentDescription>,
784 
785     /// The subpasses that make up this render pass.
786     ///
787     /// A render pass must contain at least one subpass.
788     ///
789     /// The default value is empty, which must be overridden.
790     pub subpasses: Vec<SubpassDescription>,
791 
792     /// The dependencies between subpasses.
793     ///
794     /// The default value is empty.
795     pub dependencies: Vec<SubpassDependency>,
796 
797     /// If multiview rendering is being used (the subpasses have a nonzero `view_mask`),
798     /// this specifies sets of views that may be more efficient to render concurrently, for example
799     /// because they show the same geometry from almost the same perspective. This is an
800     /// optimization hint to the implementation, and does not affect the final result.
801     ///
802     /// The value is a bitmask, so that that for example `0b11` means that the first two views are
803     /// highly correlated, and `0b101` means the first and third view are highly correlated. Each
804     /// view bit must appear in at most one element of the list.
805     ///
806     /// If multiview rendering is not being used, the value must be empty.
807     ///
808     /// The default value is empty.
809     pub correlated_view_masks: Vec<u32>,
810 
811     pub _ne: crate::NonExhaustive,
812 }
813 
814 impl Default for RenderPassCreateInfo {
815     #[inline]
default() -> Self816     fn default() -> Self {
817         Self {
818             attachments: Vec::new(),
819             subpasses: Vec::new(),
820             dependencies: Vec::new(),
821             correlated_view_masks: Vec::new(),
822             _ne: crate::NonExhaustive(()),
823         }
824     }
825 }
826 
827 /// Describes an attachment that will be used in a render pass.
828 #[derive(Clone, Copy, Debug)]
829 pub struct AttachmentDescription {
830     /// The format of the image that is going to be bound.
831     ///
832     /// The default value is `None`, which must be overridden.
833     pub format: Option<Format>,
834 
835     /// The number of samples of the image that is going to be bound.
836     ///
837     /// The default value is [`SampleCount::Sample1`].
838     pub samples: SampleCount,
839 
840     /// What the implementation should do with the attachment at the start of the subpass that first
841     /// uses it.
842     ///
843     /// The default value is [`LoadOp::DontCare`].
844     pub load_op: LoadOp,
845 
846     /// What the implementation should do with the attachment at the end of the subpass that last
847     /// uses it.
848     ///
849     /// The default value is [`StoreOp::DontCare`].
850     pub store_op: StoreOp,
851 
852     /// The equivalent of `load_op` for the stencil component of the attachment, if any. Irrelevant
853     /// if there is no stencil component.
854     ///
855     /// The default value is [`LoadOp::DontCare`].
856     pub stencil_load_op: LoadOp,
857 
858     /// The equivalent of `store_op` for the stencil component of the attachment, if any. Irrelevant
859     /// if there is no stencil component.
860     ///
861     /// The default value is [`StoreOp::DontCare`].
862     pub stencil_store_op: StoreOp,
863 
864     /// The layout that the image must in at the start of the render pass.
865     ///
866     /// The vulkano library will automatically switch to the correct layout if necessary, but it
867     /// is more efficient to set this to the correct value.
868     ///
869     /// The default value is [`ImageLayout::Undefined`], which must be overridden.
870     pub initial_layout: ImageLayout,
871 
872     /// The layout that the image will be transitioned to at the end of the render pass.
873     ///
874     /// The default value is [`ImageLayout::Undefined`], which must be overridden.
875     pub final_layout: ImageLayout,
876 
877     pub _ne: crate::NonExhaustive,
878 }
879 
880 impl Default for AttachmentDescription {
881     #[inline]
default() -> Self882     fn default() -> Self {
883         Self {
884             format: None,
885             samples: SampleCount::Sample1,
886             load_op: LoadOp::DontCare,
887             store_op: StoreOp::DontCare,
888             stencil_load_op: LoadOp::DontCare,
889             stencil_store_op: StoreOp::DontCare,
890             initial_layout: ImageLayout::Undefined,
891             final_layout: ImageLayout::Undefined,
892             _ne: crate::NonExhaustive(()),
893         }
894     }
895 }
896 
897 /// Describes one of the subpasses of a render pass.
898 ///
899 /// A subpass can use zero or more attachments of various types. Attachment types of which there can
900 /// be multiple are listed in a `Vec` in this structure. The index in these `Vec`s corresponds to
901 /// the index used for that attachment type in the shader.
902 ///
903 /// If a particular index is not used in the shader, it can be set to `None` in this structure.
904 /// This is useful if an unused index needs to be skipped but a higher index needs to be specified.
905 ///
906 /// If an attachment is used more than once, i.e. a given `AttachmentReference::attachment` occurs
907 /// more than once in the `SubpassDescription`, then their `AttachmentReference::layout` must be
908 /// the same as well.
909 #[derive(Debug, Clone)]
910 pub struct SubpassDescription {
911     /// If not `0`, enables multiview rendering, and specifies the view indices that are rendered to
912     /// in this subpass. The value is a bitmask, so that that for example `0b11` will draw to the
913     /// first two views and `0b101` will draw to the first and third view.
914     ///
915     /// If set to a nonzero value, it must be nonzero for all subpasses in the render pass, and the
916     /// [`multiview`](crate::device::Features::multiview) feature must be enabled on the device.
917     ///
918     /// The default value is `0`.
919     pub view_mask: u32,
920 
921     /// The attachments of the render pass that are to be used as input attachments in this subpass.
922     ///
923     /// If an attachment is used here for the first time in this render pass, and it's is not also
924     /// used as a color or depth/stencil attachment in this subpass, then the attachment's `load_op`
925     /// must not be [`LoadOp::Clear`].
926     ///
927     /// The default value is empty.
928     pub input_attachments: Vec<Option<AttachmentReference>>,
929 
930     /// The attachments of the render pass that are to be used as color attachments in this subpass.
931     ///
932     /// The number of color attachments must be less than the
933     /// [`max_color_attachments`](crate::device::Properties::max_color_attachments) limit of the
934     /// physical device. All color attachments must have the same `samples` value.
935     ///
936     /// The default value is empty.
937     pub color_attachments: Vec<Option<AttachmentReference>>,
938 
939     /// The attachments of the render pass that are to be used as resolve attachments in this
940     /// subpass.
941     ///
942     /// This list must either be empty or have the same length as `color_attachments`. If it's not
943     /// empty, then each resolve attachment is paired with the color attachment of the same index.
944     /// The resolve attachments must all have a `samples` value of [`SampleCount::Sample1`], while
945     /// the color attachments must have a `samples` value other than [`SampleCount::Sample1`].
946     /// Each resolve attachment must have the same `format` as the corresponding color attachment.
947     ///
948     /// The default value is empty.
949     pub resolve_attachments: Vec<Option<AttachmentReference>>,
950 
951     /// The single attachment of the render pass that is to be used as depth-stencil attachment in
952     /// this subpass.
953     ///
954     /// If set to `Some`, the referenced attachment must have the same `samples` value as those in
955     /// `color_attachments`.
956     ///
957     /// The default value is `None`.
958     pub depth_stencil_attachment: Option<AttachmentReference>,
959 
960     /// The indices of attachments of the render pass that will be preserved during this subpass.
961     ///
962     /// The referenced attachments must not be used as any other attachment type in the subpass.
963     ///
964     /// The default value is empty.
965     pub preserve_attachments: Vec<u32>,
966 
967     pub _ne: crate::NonExhaustive,
968 }
969 
970 impl Default for SubpassDescription {
971     #[inline]
default() -> Self972     fn default() -> Self {
973         Self {
974             view_mask: 0,
975             color_attachments: Vec::new(),
976             depth_stencil_attachment: None,
977             input_attachments: Vec::new(),
978             resolve_attachments: Vec::new(),
979             preserve_attachments: Vec::new(),
980             _ne: crate::NonExhaustive(()),
981         }
982     }
983 }
984 
985 /// A reference in a subpass description to a particular attachment of the render pass.
986 #[derive(Clone, Debug)]
987 pub struct AttachmentReference {
988     /// The number of the attachment being referred to.
989     ///
990     /// The default value is `0`.
991     pub attachment: u32,
992 
993     /// The image layout that the attachment should be transitioned to at the start of the subpass.
994     ///
995     /// The layout is restricted by the type of attachment that an attachment is being used as. A
996     /// full listing of allowed layouts per type can be found in
997     /// [the Vulkan specification](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap8.html#attachment-type-imagelayout).
998     ///
999     /// The default value is [`ImageLayout::Undefined`], which must be overridden.
1000     pub layout: ImageLayout,
1001 
1002     /// For references to input attachments, the aspects of the image that should be selected.
1003     /// For attachment types other than input attachments, the value must be empty.
1004     ///
1005     /// If empty, all aspects available in the input attachment's `format` will be selected.
1006     /// If any fields are set, they must be aspects that are available in the `format` of the
1007     /// attachment.
1008     ///
1009     /// If the value is neither empty nor identical to the aspects of the `format`, the device API
1010     /// version must be at least 1.1, or either the
1011     /// [`khr_create_renderpass2`](crate::device::DeviceExtensions::khr_create_renderpass2) or the
1012     /// [`khr_maintenance2`](crate::device::DeviceExtensions::khr_maintenance2) extensions must be
1013     /// enabled on the device.
1014     ///
1015     /// The default value is [`ImageAspects::empty()`].
1016     pub aspects: ImageAspects,
1017 
1018     pub _ne: crate::NonExhaustive,
1019 }
1020 
1021 impl Default for AttachmentReference {
1022     #[inline]
default() -> Self1023     fn default() -> Self {
1024         Self {
1025             attachment: 0,
1026             layout: ImageLayout::Undefined,
1027             aspects: ImageAspects::empty(),
1028             _ne: crate::NonExhaustive(()),
1029         }
1030     }
1031 }
1032 
1033 /// A dependency between two subpasses of a render pass.
1034 ///
1035 /// The implementation is allowed to change the order of the subpasses within a render pass, unless
1036 /// you specify that there exists a dependency between two subpasses (ie. the result of one will be
1037 /// used as the input of another one). Subpass dependencies work similar to pipeline barriers,
1038 /// except that they operate on whole subpasses instead of individual images.
1039 ///
1040 /// If `src_subpass` and `dst_subpass` are equal, then this specifies a
1041 /// [subpass self-dependency](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap7.html#synchronization-pipeline-barriers-subpass-self-dependencies).
1042 /// The `src_stages` must all be
1043 /// [logically earlier in the pipeline](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap7.html#synchronization-pipeline-stages-order)
1044 /// than the `dst_stages`, and if they both contain a
1045 /// [framebuffer-space stage](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap7.html#synchronization-framebuffer-regions),
1046 /// then `by_region` must be activated.
1047 ///
1048 /// If `src_subpass` or `dst_subpass` are set to `None`, this specifies an external
1049 /// dependency. An external dependency specifies a dependency on commands that were submitted before
1050 /// the render pass instance began (for `src_subpass`), or on commands that will be submitted
1051 /// after the render pass instance ends (for `dst_subpass`). The values must not both be
1052 /// `None`.
1053 #[derive(Clone, Debug, PartialEq, Eq)]
1054 pub struct SubpassDependency {
1055     /// The index of the subpass that writes the data that `dst_subpass` is going to use.
1056     ///
1057     /// `None` specifies an external dependency.
1058     ///
1059     /// The default value is `None`.
1060     pub src_subpass: Option<u32>,
1061 
1062     /// The index of the subpass that reads the data that `src_subpass` wrote.
1063     ///
1064     /// `None` specifies an external dependency.
1065     ///
1066     /// The default value is `None`.
1067     pub dst_subpass: Option<u32>,
1068 
1069     /// The pipeline stages that must be finished on `src_subpass` before the
1070     /// `dst_stages` of `dst_subpass` can start.
1071     ///
1072     /// The default value is [`PipelineStages::empty()`].
1073     pub src_stages: PipelineStages,
1074 
1075     /// The pipeline stages of `dst_subpass` that must wait for the `src_stages` of
1076     /// `src_subpass` to be finished. Stages that are earlier than the stages specified here can
1077     /// start before the `src_stages` are finished.
1078     ///
1079     /// The default value is [`PipelineStages::empty()`].
1080     pub dst_stages: PipelineStages,
1081 
1082     /// The way `src_subpass` accesses the attachments on which we depend.
1083     ///
1084     /// The default value is [`AccessFlags::empty()`].
1085     pub src_access: AccessFlags,
1086 
1087     /// The way `dst_subpass` accesses the attachments on which we depend.
1088     ///
1089     /// The default value is [`AccessFlags::empty()`].
1090     pub dst_access: AccessFlags,
1091 
1092     /// Dependency flags that modify behavior of the subpass dependency.
1093     ///
1094     /// If a `src_subpass` equals `dst_subpass`, then:
1095     /// - If `src_stages` and `dst_stages` both contain framebuffer-space stages,
1096     ///   this must include [`BY_REGION`].
1097     /// - If the subpass's `view_mask` has more than one view,
1098     ///   this must include [`VIEW_LOCAL`].
1099     ///
1100     /// The default value is [`DependencyFlags::empty()`].
1101     ///
1102     /// [`BY_REGION`]: crate::sync::DependencyFlags::BY_REGION
1103     /// [`VIEW_LOCAL`]: crate::sync::DependencyFlags::VIEW_LOCAL
1104     pub dependency_flags: DependencyFlags,
1105 
1106     /// If multiview rendering is being used (the subpasses have a nonzero `view_mask`), and
1107     /// `dependency_flags` includes [`VIEW_LOCAL`], specifies an offset relative to the view index
1108     /// of `dst_subpass`: each view `d` in `dst_subpass` depends on view `d + view_offset` in
1109     /// `src_subpass`. If the source view index does not exist, the dependency is ignored for
1110     /// that view.
1111     ///
1112     /// If `dependency_flags` does not include [`VIEW_LOCAL`], or if `src_subpass` and
1113     /// `dst_subpass` are the same, the value must be `0`.
1114     ///
1115     /// The default value is `0`.
1116     ///
1117     /// [`VIEW_LOCAL`]: crate::sync::DependencyFlags::VIEW_LOCAL
1118     pub view_offset: i32,
1119 
1120     pub _ne: crate::NonExhaustive,
1121 }
1122 
1123 impl Default for SubpassDependency {
1124     #[inline]
default() -> Self1125     fn default() -> Self {
1126         Self {
1127             src_subpass: None,
1128             dst_subpass: None,
1129             src_stages: PipelineStages::empty(),
1130             dst_stages: PipelineStages::empty(),
1131             src_access: AccessFlags::empty(),
1132             dst_access: AccessFlags::empty(),
1133             dependency_flags: DependencyFlags::empty(),
1134             view_offset: 0,
1135             _ne: crate::NonExhaustive(()),
1136         }
1137     }
1138 }
1139 
1140 vulkan_enum! {
1141     #[non_exhaustive]
1142 
1143     /// Describes what the implementation should do with an attachment at the start of the subpass.
1144     LoadOp = AttachmentLoadOp(i32);
1145 
1146     /// The content of the attachment will be loaded from memory. This is what you want if you want
1147     /// to draw over something existing.
1148     ///
1149     /// While this is the most intuitive option, it is also the slowest because it uses a lot of
1150     /// memory bandwidth.
1151     Load = LOAD,
1152 
1153     /// The content of the attachment will be filled by the implementation with a uniform value
1154     /// that you must provide when you start drawing.
1155     ///
1156     /// This is what you usually use at the start of a frame, in order to reset the content of
1157     /// the color, depth and/or stencil buffers.
1158     Clear = CLEAR,
1159 
1160     /// The attachment will have undefined content.
1161     ///
1162     /// This is what you should use for attachments that you intend to entirely cover with draw
1163     /// commands.
1164     /// If you are going to fill the attachment with a uniform value, it is better to use `Clear`
1165     /// instead.
1166     DontCare = DONT_CARE,
1167 
1168     /* TODO: enable
1169     // TODO: document
1170     None = NONE_EXT {
1171         device_extensions: [ext_load_store_op_none],
1172     },*/
1173 }
1174 
1175 vulkan_enum! {
1176     #[non_exhaustive]
1177 
1178     /// Describes what the implementation should do with an attachment after all the subpasses have
1179     /// completed.
1180     StoreOp = AttachmentStoreOp(i32);
1181 
1182     /// The attachment will be stored. This is what you usually want.
1183     ///
1184     /// While this is the most intuitive option, it is also slower than `DontCare` because it can
1185     /// take time to write the data back to memory.
1186     Store = STORE,
1187 
1188     /// What happens is implementation-specific.
1189     ///
1190     /// This is purely an optimization compared to `Store`. The implementation doesn't need to copy
1191     /// from the internal cache to the memory, which saves memory bandwidth.
1192     ///
1193     /// This doesn't mean that the data won't be copied, as an implementation is also free to not
1194     /// use a cache and write the output directly in memory. In other words, the content of the
1195     /// image will be undefined.
1196     DontCare = DONT_CARE,
1197 
1198     /* TODO: enable
1199     // TODO: document
1200     None = NONE {
1201         api_version: V1_3,
1202         device_extensions: [khr_dynamic_rendering, ext_load_store_op_none, qcom_render_pass_store_ops],
1203     },*/
1204 }
1205 
1206 vulkan_bitflags_enum! {
1207     #[non_exhaustive]
1208 
1209     /// A set of [`ResolveMode`] values.
1210     ResolveModes,
1211 
1212     /// Possible resolve modes for attachments.
1213     ResolveMode,
1214 
1215     = ResolveModeFlags(u32);
1216 
1217     /// The resolved sample is taken from sample number zero, the other samples are ignored.
1218     ///
1219     /// This mode is supported for depth and stencil formats, and for color images with an integer
1220     /// format.
1221     SAMPLE_ZERO, SampleZero = SAMPLE_ZERO,
1222 
1223     /// The resolved sample is calculated from the average of the samples.
1224     ///
1225     /// This mode is supported for depth formats, and for color images with a non-integer format.
1226     AVERAGE, Average = AVERAGE,
1227 
1228     /// The resolved sample is calculated from the minimum of the samples.
1229     ///
1230     /// This mode is supported for depth and stencil formats only.
1231     MIN, Min = MIN,
1232 
1233     /// The resolved sample is calculated from the maximum of the samples.
1234     ///
1235     /// This mode is supported for depth and stencil formats only.
1236     MAX, Max = MAX,
1237 }
1238 
1239 #[derive(Clone, Copy, Debug)]
1240 pub(crate) struct AttachmentUse {
1241     first_use_subpass: u32,
1242     last_use_subpass: u32,
1243 }
1244 
1245 #[cfg(test)]
1246 mod tests {
1247     use crate::{
1248         format::Format,
1249         render_pass::{RenderPass, RenderPassCreationError},
1250     };
1251 
1252     #[test]
empty()1253     fn empty() {
1254         let (device, _) = gfx_dev_and_queue!();
1255         let _ = RenderPass::empty_single_pass(device).unwrap();
1256     }
1257 
1258     #[test]
too_many_color_atch()1259     fn too_many_color_atch() {
1260         let (device, _) = gfx_dev_and_queue!();
1261 
1262         if device.physical_device().properties().max_color_attachments >= 10 {
1263             return; // test ignored
1264         }
1265 
1266         let rp = single_pass_renderpass!(
1267             device,
1268             attachments: {
1269                 a1: { load: Clear, store: DontCare, format: Format::R8G8B8A8_UNORM, samples: 1, },
1270                 a2: { load: Clear, store: DontCare, format: Format::R8G8B8A8_UNORM, samples: 1, },
1271                 a3: { load: Clear, store: DontCare, format: Format::R8G8B8A8_UNORM, samples: 1, },
1272                 a4: { load: Clear, store: DontCare, format: Format::R8G8B8A8_UNORM, samples: 1, },
1273                 a5: { load: Clear, store: DontCare, format: Format::R8G8B8A8_UNORM, samples: 1, },
1274                 a6: { load: Clear, store: DontCare, format: Format::R8G8B8A8_UNORM, samples: 1, },
1275                 a7: { load: Clear, store: DontCare, format: Format::R8G8B8A8_UNORM, samples: 1, },
1276                 a8: { load: Clear, store: DontCare, format: Format::R8G8B8A8_UNORM, samples: 1, },
1277                 a9: { load: Clear, store: DontCare, format: Format::R8G8B8A8_UNORM, samples: 1, },
1278                 a10: { load: Clear, store: DontCare, format: Format::R8G8B8A8_UNORM, samples: 1, },
1279             },
1280             pass: {
1281                 color: [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10],
1282                 depth_stencil: {},
1283             },
1284         );
1285 
1286         match rp {
1287             Err(RenderPassCreationError::SubpassMaxColorAttachmentsExceeded { .. }) => (),
1288             _ => panic!(),
1289         }
1290     }
1291 
1292     #[test]
non_zero_granularity()1293     fn non_zero_granularity() {
1294         let (device, _) = gfx_dev_and_queue!();
1295 
1296         let rp = single_pass_renderpass!(
1297             device,
1298             attachments: {
1299                 a: { load: Clear, store: DontCare, format: Format::R8G8B8A8_UNORM, samples: 1, },
1300             },
1301             pass: {
1302                 color: [a],
1303                 depth_stencil: {},
1304             },
1305         )
1306         .unwrap();
1307 
1308         let granularity = rp.granularity();
1309         assert_ne!(granularity[0], 0);
1310         assert_ne!(granularity[1], 0);
1311     }
1312 }
1313