1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
use crate::shared;

#[repr(C)]
pub struct ValidatorOptions {
    _unused: [u8; 0],
}

#[derive(Copy, Clone, Debug)]
#[repr(C)]
pub enum ValidatorLimits {
    StructMembers,
    StructDepth,
    LocalVariables,
    GlobalVariables,
    SwitchBranches,
    FunctionArgs,
    ControlFlowNestingDepth,
    AccessChainIndexes,
    IdBound,
}

extern "C" {
    /// Validates a SPIR-V binary for correctness. Any errors will be written into
    /// *diagnostic if diagnostic is non-null, otherwise the context's message
    /// consumer will be used.
    ///
    /// Validate for SPIR-V spec rules for the SPIR-V version named in the
    /// binary's header (at word offset 1).  Additionally, if the context target
    /// environment is a client API (such as Vulkan 1.1), then validate for that
    /// client API version, to the extent that it is verifiable from data in the
    /// binary itself.
    #[link_name = "spvValidate"]
    pub fn validate(
        tool: *const shared::ToolContext,
        binary: *const shared::Binary,
        diagnostic: *mut *mut crate::diagnostics::Diagnostic,
    ) -> crate::shared::SpirvResult;

    /// Validates a SPIR-V binary for correctness. Uses the provided Validator
    /// options. Any errors will be written into *diagnostic if diagnostic is
    /// non-null, otherwise the context's message consumer will be used.
    ///
    /// Validate for SPIR-V spec rules for the SPIR-V version named in the
    /// binary's header (at word offset 1).  Additionally, if the context target
    /// environment is a client API (such as Vulkan 1.1), then validate for that
    /// client API version, to the extent that it is verifiable from data in the
    /// binary itself, or in the validator options.
    #[link_name = "spvValidateWithOptions"]
    pub fn validate_with_options(
        tool: *const shared::ToolContext,
        options: *const ValidatorOptions,
        binary: *const shared::Binary,
        diagnostic: *mut *mut crate::diagnostics::Diagnostic,
    ) -> crate::shared::SpirvResult;

    /// Creates a Validator options object with default options. Returns a valid
    /// options object. The object remains valid until it is passed into
    /// spvValidatorOptionsDestroy.
    #[link_name = "spvValidatorOptionsCreate"]
    pub fn validator_options_create() -> *mut ValidatorOptions;

    /// Destroys the given Validator options object.
    #[link_name = "spvValidatorOptionsDestroy"]
    pub fn validator_options_destroy(opts: *mut ValidatorOptions);

    /// Records the maximum Universal Limit that is considered valid in the given
    /// Validator options object. <options> argument must be a valid options object.
    #[link_name = "spvValidatorOptionsSetUniversalLimit"]
    pub fn validator_options_set_limit(
        opts: *mut ValidatorOptions,
        limit_type: ValidatorLimits,
        limit: u32,
    );

    /// Record whether or not the validator should relax the rules on types for
    /// stores to structs.  When relaxed, it will allow a type mismatch as long as
    /// the types are structs with the same layout.  Two structs have the same layout
    /// if
    ///
    /// 1) the members of the structs are either the same type or are structs with
    /// same layout, and
    ///
    /// 2) the decorations that affect the memory layout are identical for both
    /// types.  Other decorations are not relevant.
    #[link_name = "spvValidatorOptionsSetRelaxStoreStruct"]
    pub fn validator_options_set_relax_store_struct(opts: *mut ValidatorOptions, toggle: bool);

    /// Records whether or not the validator should relax the rules on pointer usage
    /// in logical addressing mode.
    ///
    /// When relaxed, it will allow the following usage cases of pointers:
    /// 1) OpVariable allocating an object whose type is a pointer type
    /// 2) OpReturnValue returning a pointer value
    #[link_name = "spvValidatorOptionsSetRelaxLogicalPointer"]
    pub fn validator_options_set_relax_logical_pointer(opts: *mut ValidatorOptions, toggle: bool);

    /// Records whether or not the validator should relax the rules because it is
    /// expected that the optimizations will make the code legal.
    ///
    /// When relaxed, it will allow the following:
    /// 1) It will allow relaxed logical pointers.  Setting this option will also
    ///    set that option.
    /// 2) Pointers that are pass as parameters to function calls do not have to
    ///    match the storage class of the formal parameter.
    /// 3) Pointers that are actaul parameters on function calls do not have to point
    ///    to the same type pointed as the formal parameter.  The types just need to
    ///    logically match.
    #[link_name = "spvValidatorOptionsSetBeforeHlslLegalization"]
    pub fn validator_options_set_before_legalization(opts: *mut ValidatorOptions, toggle: bool);

    /// Records whether the validator should use "relaxed" block layout rules.
    /// Relaxed layout rules are described by Vulkan extension
    /// VK_KHR_relaxed_block_layout, and they affect uniform blocks, storage blocks,
    /// and push constants.
    ///
    /// This is enabled by default when targeting Vulkan 1.1 or later.
    /// Relaxed layout is more permissive than the default rules in Vulkan 1.0.
    #[link_name = "spvValidatorOptionsSetRelaxBlockLayout"]
    pub fn validator_options_set_relax_block_layout(opts: *mut ValidatorOptions, toggle: bool);

    /// Records whether the validator should use standard block layout rules for
    /// uniform blocks.
    #[link_name = "spvValidatorOptionsSetUniformBufferStandardLayout"]
    pub fn validator_options_set_uniform_buffer_standard_layout(
        opts: *mut ValidatorOptions,
        toggle: bool,
    );

    /// Records whether the validator should use "scalar" block layout rules.
    /// Scalar layout rules are more permissive than relaxed block layout.
    ///
    /// See Vulkan extnesion VK_EXT_scalar_block_layout.  The scalar alignment is
    /// defined as follows:
    /// - scalar alignment of a scalar is the scalar size
    /// - scalar alignment of a vector is the scalar alignment of its component
    /// - scalar alignment of a matrix is the scalar alignment of its component
    /// - scalar alignment of an array is the scalar alignment of its element
    /// - scalar alignment of a struct is the max scalar alignment among its
    ///   members
    ///
    /// For a struct in Uniform, StorageClass, or PushConstant:
    /// - a member Offset must be a multiple of the member's scalar alignment
    /// - ArrayStride or MatrixStride must be a multiple of the array or matrix
    ///   scalar alignment
    #[link_name = "spvValidatorOptionsSetScalarBlockLayout"]
    pub fn validator_options_set_scalar_block_layout(opts: *mut ValidatorOptions, toggle: bool);

    /// Records whether or not the validator should skip validating standard
    /// uniform/storage block layout.
    #[link_name = "spvValidatorOptionsSetSkipBlockLayout"]
    pub fn validator_options_set_skip_block_layout(opts: *mut ValidatorOptions, toggle: bool);
}