fn descriptor_requirements_of(
    spirv: &Spirv,
    pointed_ty: Id,
    pointer_storage: &StorageClass,
    force_combined_image_sampled: bool,
) -> Option<DescriptorRequirements> {
    let id_info = spirv.id(pointed_ty);

    match id_info.instruction() {
        Instruction::TypeStruct { .. } => {
            let decoration_block = id_info.iter_decoration().any(|instruction| {
                matches!(
                    instruction,
                    Instruction::Decorate {
                        decoration: Decoration::Block,
                        ..
                    }
                )
            });

            let decoration_buffer_block = id_info.iter_decoration().any(|instruction| {
                matches!(
                    instruction,
                    Instruction::Decorate {
                        decoration: Decoration::BufferBlock,
                        ..
                    }
                )
            });

            assert!(
                decoration_block ^ decoration_buffer_block,
                "Structs in shader interface are expected to be decorated with one of Block or BufferBlock"
            );

            let mut reqs = DescriptorRequirements {
                descriptor_count: 1,
                ..Default::default()
            };

            if decoration_buffer_block
                || decoration_block && *pointer_storage == StorageClass::StorageBuffer
            {
                // Determine whether all members have a NonWritable decoration.
                let nonwritable = id_info.iter_members().all(|member_info| {
                    member_info.iter_decoration().any(|instruction| {
                        matches!(
                            instruction,
                            Instruction::MemberDecorate {
                                decoration: Decoration::NonWritable,
                                ..
                            }
                        )
                    })
                });

                reqs.descriptor_types = vec![
                    DescriptorType::StorageBuffer,
                    DescriptorType::StorageBufferDynamic,
                ];
                reqs.mutable = !nonwritable;
            } else {
                reqs.descriptor_types = vec![
                    DescriptorType::UniformBuffer,
                    DescriptorType::UniformBufferDynamic,
                ];
            };

            Some(reqs)
        }
        &Instruction::TypeImage {
            ref dim,
            arrayed,
            ms,
            sampled,
            ref image_format,
            ..
        } => {
            let multisampled = ms != 0;
            assert!(sampled != 0, "Vulkan requires that variables of type OpTypeImage have a Sampled operand of 1 or 2");
            let format: Option<Format> = image_format.clone().into();

            match dim {
                Dim::SubpassData => {
                    assert!(
                        !force_combined_image_sampled,
                        "An OpTypeSampledImage can't point to \
                                                                an OpTypeImage whose dimension is \
                                                                SubpassData"
                    );
                    assert!(
                        *image_format == ImageFormat::Unknown,
                        "If Dim is SubpassData, Image Format must be Unknown"
                    );
                    assert!(sampled == 2, "If Dim is SubpassData, Sampled must be 2");
                    assert!(arrayed == 0, "If Dim is SubpassData, Arrayed must be 0");

                    Some(DescriptorRequirements {
                        descriptor_types: vec![DescriptorType::InputAttachment],
                        descriptor_count: 1,
                        multisampled,
                        ..Default::default()
                    })
                }
                Dim::Buffer => {
                    let mut reqs = DescriptorRequirements {
                        descriptor_count: 1,
                        format,
                        ..Default::default()
                    };

                    if sampled == 1 {
                        reqs.descriptor_types = vec![DescriptorType::UniformTexelBuffer];
                    } else {
                        reqs.descriptor_types = vec![DescriptorType::StorageTexelBuffer];
                        reqs.mutable = true;
                    }

                    Some(reqs)
                }
                _ => {
                    let image_view_type = Some(match (dim, arrayed) {
                        (Dim::Dim1D, 0) => ImageViewType::Dim1d,
                        (Dim::Dim1D, 1) => ImageViewType::Dim1dArray,
                        (Dim::Dim2D, 0) => ImageViewType::Dim2d,
                        (Dim::Dim2D, 1) => ImageViewType::Dim2dArray,
                        (Dim::Dim3D, 0) => ImageViewType::Dim3d,
                        (Dim::Dim3D, 1) => panic!("Vulkan doesn't support arrayed 3D textures"),
                        (Dim::Cube, 0) => ImageViewType::Cube,
                        (Dim::Cube, 1) => ImageViewType::CubeArray,
                        (Dim::Rect, _) => panic!("Vulkan doesn't support rectangle textures"),
                        _ => unreachable!(),
                    });

                    let mut reqs = DescriptorRequirements {
                        descriptor_count: 1,
                        format,
                        multisampled,
                        image_view_type,
                        ..Default::default()
                    };

                    if force_combined_image_sampled {
                        assert!(
                            sampled == 1,
                            "A combined image sampler must not reference a storage image"
                        );

                        reqs.descriptor_types = vec![DescriptorType::CombinedImageSampler];
                    } else {
                        if sampled == 1 {
                            reqs.descriptor_types = vec![DescriptorType::SampledImage];
                        } else {
                            reqs.descriptor_types = vec![DescriptorType::StorageImage];
                            reqs.mutable = true;
                        }
                    };

                    Some(reqs)
                }
            }
        }

        &Instruction::TypeSampledImage { image_type, .. } => {
            descriptor_requirements_of(spirv, image_type, pointer_storage, true)
        }

        &Instruction::TypeSampler { .. } => Some(DescriptorRequirements {
            descriptor_types: vec![DescriptorType::Sampler],
            descriptor_count: 1,
            ..Default::default()
        }),

        &Instruction::TypeArray {
            element_type,
            length,
            ..
        } => {
            let reqs = match descriptor_requirements_of(spirv, element_type, pointer_storage, false)
            {
                None => return None,
                Some(v) => v,
            };
            assert_eq!(reqs.descriptor_count, 1); // TODO: implement?
            let len = match spirv.id(length).instruction() {
                &Instruction::Constant { ref value, .. } => value,
                _ => panic!("failed to find array length"),
            };
            let len = len.iter().rev().fold(0, |a, &b| (a << 32) | b as u64);

            Some(DescriptorRequirements {
                descriptor_count: len as u32,
                ..reqs
            })
        }

        &Instruction::TypeRuntimeArray { element_type, .. } => {
            let reqs = match descriptor_requirements_of(spirv, element_type, pointer_storage, false)
            {
                None => return None,
                Some(v) => v,
            };
            assert_eq!(reqs.descriptor_count, 1); // TODO: implement?

            Some(DescriptorRequirements {
                descriptor_count: 0,
                ..reqs
            })
        }

        _ => None,
    }
}
/// Returns a `DescriptorRequirements` value for the pointed type.
///
/// See also section 14.5.2 of the Vulkan specs: Descriptor Set Interface
Returns a `DescriptorRequirements` value for the pointed type.
See also section 14.5.2 of the Vulkan specs: Descriptor Set Interface
Returns a ` DescriptorRequirements ` value for the pointed type . See also section 14 . 5 . 2 of the Vulkan specs : Descriptor Set Interface
fn descriptor_requirements_of(
    spirv: &Spirv,
    pointed_ty: Id,
    pointer_storage: &StorageClass,
    force_combined_image_sampled: bool,
) -> Option<DescriptorRequirements> {
    let id_info = spirv.id(pointed_ty);
    match id_info.instruction() {
        Instruction::TypeStruct { .. } => {
            let decoration_block = id_info.iter_decoration().any(|instruction| {
                matches!(
                    instruction,
                    Instruction::Decorate {
                        decoration: Decoration::Block,
                        ..
                    }
                )
            });
            let decoration_buffer_block = id_info.iter_decoration().any(|instruction| {
                matches!(
                    instruction,
                    Instruction::Decorate {
                        decoration: Decoration::BufferBlock,
                        ..
                    }
                )
            });
            assert!(
                decoration_block ^ decoration_buffer_block,
                "Structs in shader interface are expected to be decorated with one of Block or BufferBlock"
            );
            let mut reqs = DescriptorRequirements {
                descriptor_count: 1,
                ..Default::default()
            };
            if decoration_buffer_block
                || decoration_block && *pointer_storage == StorageClass::StorageBuffer
            {
                // Determine whether all members have a NonWritable decoration.
                let nonwritable = id_info.iter_members().all(|member_info| {
                    member_info.iter_decoration().any(|instruction| {
                        matches!(
                            instruction,
                            Instruction::MemberDecorate {
                                decoration: Decoration::NonWritable,
                                ..
                            }
                        )
                    })
                });
                reqs.descriptor_types = vec![
                    DescriptorType::StorageBuffer,
                    DescriptorType::StorageBufferDynamic,
                ];
                reqs.mutable = !nonwritable;
            } else {
                reqs.descriptor_types = vec![
                    DescriptorType::UniformBuffer,
                    DescriptorType::UniformBufferDynamic,
                ];
            };
            Some(reqs)
        }
        &Instruction::TypeImage {
            ref dim,
            arrayed,
            ms,
            sampled,
            ref image_format,
            ..
        } => {
            let multisampled = ms != 0;
            assert!(sampled != 0, "Vulkan requires that variables of type OpTypeImage have a Sampled operand of 1 or 2");
            let format: Option<Format> = image_format.clone().into();
            match dim {
                Dim::SubpassData => {
                    assert!(
                        !force_combined_image_sampled,
                        "An OpTypeSampledImage can't point to \
                                                                an OpTypeImage whose dimension is \
                                                                SubpassData"
                    );
                    assert!(
                        *image_format == ImageFormat::Unknown,
                        "If Dim is SubpassData, Image Format must be Unknown"
                    );
                    assert!(sampled == 2, "If Dim is SubpassData, Sampled must be 2");
                    assert!(arrayed == 0, "If Dim is SubpassData, Arrayed must be 0");
                    Some(DescriptorRequirements {
                        descriptor_types: vec![DescriptorType::InputAttachment],
                        descriptor_count: 1,
                        multisampled,
                        ..Default::default()
                    })
                }
                Dim::Buffer => {
                    let mut reqs = DescriptorRequirements {
                        descriptor_count: 1,
                        format,
                        ..Default::default()
                    };
                    if sampled == 1 {
                        reqs.descriptor_types = vec![DescriptorType::UniformTexelBuffer];
                    } else {
                        reqs.descriptor_types = vec![DescriptorType::StorageTexelBuffer];
                        reqs.mutable = true;
                    }
                    Some(reqs)
                }
                _ => {
                    let image_view_type = Some(match (dim, arrayed) {
                        (Dim::Dim1D, 0) => ImageViewType::Dim1d,
                        (Dim::Dim1D, 1) => ImageViewType::Dim1dArray,
                        (Dim::Dim2D, 0) => ImageViewType::Dim2d,
                        (Dim::Dim2D, 1) => ImageViewType::Dim2dArray,
                        (Dim::Dim3D, 0) => ImageViewType::Dim3d,
                        (Dim::Dim3D, 1) => panic!("Vulkan doesn't support arrayed 3D textures"),
                        (Dim::Cube, 0) => ImageViewType::Cube,
                        (Dim::Cube, 1) => ImageViewType::CubeArray,
                        (Dim::Rect, _) => panic!("Vulkan doesn't support rectangle textures"),
                        _ => unreachable!(),
                    });
                    let mut reqs = DescriptorRequirements {
                        descriptor_count: 1,
                        format,
                        multisampled,
                        image_view_type,
                        ..Default::default()
                    };
                    if force_combined_image_sampled {
                        assert!(
                            sampled == 1,
                            "A combined image sampler must not reference a storage image"
                        );
                        reqs.descriptor_types = vec![DescriptorType::CombinedImageSampler];
                    } else {
                        if sampled == 1 {
                            reqs.descriptor_types = vec![DescriptorType::SampledImage];
                        } else {
                            reqs.descriptor_types = vec![DescriptorType::StorageImage];
                            reqs.mutable = true;
                        }
                    };
                    Some(reqs)
                }
            }
        }
        &Instruction::TypeSampledImage { image_type, .. } => {
            descriptor_requirements_of(spirv, image_type, pointer_storage, true)
        }
        &Instruction::TypeSampler { .. } => Some(DescriptorRequirements {
            descriptor_types: vec![DescriptorType::Sampler],
            descriptor_count: 1,
            ..Default::default()
        }),
        &Instruction::TypeArray {
            element_type,
            length,
            ..
        } => {
            let reqs = match descriptor_requirements_of(spirv, element_type, pointer_storage, false)
            {
                None => return None,
                Some(v) => v,
            };
            assert_eq!(reqs.descriptor_count, 1); // TODO: implement?
            let len = match spirv.id(length).instruction() {
                &Instruction::Constant { ref value, .. } => value,
                _ => panic!("failed to find array length"),
            };
            let len = len.iter().rev().fold(0, |a, &b| (a << 32) | b as u64);
            Some(DescriptorRequirements {
                descriptor_count: len as u32,
                ..reqs
            })
        }
        &Instruction::TypeRuntimeArray { element_type, .. } => {
            let reqs = match descriptor_requirements_of(spirv, element_type, pointer_storage, false)
            {
                None => return None,
                Some(v) => v,
            };
            assert_eq!(reqs.descriptor_count, 1); // TODO: implement?
            Some(DescriptorRequirements {
                descriptor_count: 0,
                ..reqs
            })
        }
        _ => None,
    }
}
fn descriptor_requirements_of ( spirv : & Spirv , pointed_ty : Id , pointer_storage : & StorageClass , force_combined_image_sampled : bool , ) -> Option < DescriptorRequirements > { let id_info = spirv . id ( pointed_ty ) ; match id_info . instruction ( ) { Instruction :: TypeStruct { .. } => { let decoration_block = id_info . iter_decoration ( ) . any ( | instruction | { matches ! ( instruction Instruction Decorate { decoration Decoration Block } ) } ) ; let decoration_buffer_block = id_info . iter_decoration ( ) . any ( | instruction | { matches ! ( instruction Instruction Decorate { decoration Decoration BufferBlock } ) } ) ; assert ! ( decoration_block decoration_buffer_block " " ) ; let mut reqs = DescriptorRequirements { descriptor_count : 1 , .. Default :: default ( ) } ; if decoration_buffer_block || decoration_block && * pointer_storage == StorageClass :: StorageBuffer { // Determine whether all members have a NonWritable decoration. let nonwritable = id_info . iter_members ( ) . all ( | member_info | { member_info . iter_decoration ( ) . any ( | instruction | { matches ! ( instruction Instruction MemberDecorate { decoration Decoration NonWritable } ) } ) } ) ; reqs . descriptor_types = vec ! [ DescriptorType StorageBuffer DescriptorType StorageBufferDynamic ] ; reqs . mutable = ! nonwritable ; } else { reqs . descriptor_types = vec ! [ DescriptorType UniformBuffer DescriptorType UniformBufferDynamic ] ; } ; Some ( reqs ) } & Instruction :: TypeImage { ref dim , arrayed , ms , sampled , ref image_format , .. } => { let multisampled = ms != 0 ; assert ! ( sampled 0 " " ) ; let format : Option < Format > = image_format . clone ( ) . into ( ) ; match dim { Dim :: SubpassData => { assert ! ( force_combined_image_sampled " \
 \
 " ) ; assert ! ( image_format ImageFormat Unknown " " ) ; assert ! ( sampled 2 " " ) ; assert ! ( arrayed 0 " " ) ; Some ( DescriptorRequirements { descriptor_types : vec ! [ DescriptorType InputAttachment ] , descriptor_count : 1 , multisampled , .. Default :: default ( ) } ) } Dim :: Buffer => { let mut reqs = DescriptorRequirements { descriptor_count : 1 , format , .. Default :: default ( ) } ; if sampled == 1 { reqs . descriptor_types = vec ! [ DescriptorType UniformTexelBuffer ] ; } else { reqs . descriptor_types = vec ! [ DescriptorType StorageTexelBuffer ] ; reqs . mutable = true ; } Some ( reqs ) } _ => { let image_view_type = Some ( match ( dim , arrayed ) { ( Dim :: Dim1D , 0 ) => ImageViewType :: Dim1d , ( Dim :: Dim1D , 1 ) => ImageViewType :: Dim1dArray , ( Dim :: Dim2D , 0 ) => ImageViewType :: Dim2d , ( Dim :: Dim2D , 1 ) => ImageViewType :: Dim2dArray , ( Dim :: Dim3D , 0 ) => ImageViewType :: Dim3d , ( Dim :: Dim3D , 1 ) => panic ! ( " " ) , ( Dim :: Cube , 0 ) => ImageViewType :: Cube , ( Dim :: Cube , 1 ) => ImageViewType :: CubeArray , ( Dim :: Rect , _ ) => panic ! ( " " ) , _ => unreachable ! ( ) , } ) ; let mut reqs = DescriptorRequirements { descriptor_count : 1 , format , multisampled , image_view_type , .. Default :: default ( ) } ; if force_combined_image_sampled { assert ! ( sampled 1 " " ) ; reqs . descriptor_types = vec ! [ DescriptorType CombinedImageSampler ] ; } else { if sampled == 1 { reqs . descriptor_types = vec ! [ DescriptorType SampledImage ] ; } else { reqs . descriptor_types = vec ! [ DescriptorType StorageImage ] ; reqs . mutable = true ; } } ; Some ( reqs ) } } } & Instruction :: TypeSampledImage { image_type , .. } => { descriptor_requirements_of ( spirv , image_type , pointer_storage , true ) } & Instruction :: TypeSampler { .. } => Some ( DescriptorRequirements { descriptor_types : vec ! [ DescriptorType Sampler ] , descriptor_count : 1 , .. Default :: default ( ) } ) , & Instruction :: TypeArray { element_type , length , .. } => { let reqs = match descriptor_requirements_of ( spirv , element_type , pointer_storage , false ) { None => return None , Some ( v ) => v , } ; assert_eq ! ( reqs descriptor_count 1 ) ; // TODO: implement? let len = match spirv . id ( length ) . instruction ( ) { & Instruction :: Constant { ref value , .. } => value , _ => panic ! ( " " ) , } ; let len = len . iter ( ) . rev ( ) . fold ( 0 , | a , & b | ( a << 32 ) | b as u64 ) ; Some ( DescriptorRequirements { descriptor_count : len as u32 , .. reqs } ) } & Instruction :: TypeRuntimeArray { element_type , .. } => { let reqs = match descriptor_requirements_of ( spirv , element_type , pointer_storage , false ) { None => return None , Some ( v ) => v , } ; assert_eq ! ( reqs descriptor_count 1 ) ; // TODO: implement? Some ( DescriptorRequirements { descriptor_count : 0 , .. reqs } ) } _ => None , } }
Returns a `DescriptorRequirements` value for the pointed type.
Returns a ` DescriptorRequirements ` value for the pointed type .
spirv
&Spirv
pointed_ty
Id
pointer_storage
&StorageClass
force_combined_image_sampled
bool
spirv
&Spirv
pointed_ty
Id
pointer_storage
&StorageClass
force_combined_image_sampled
bool