spirv_tools_sys/
shared.rs

1use std::fmt;
2
3/// Certain target environments impose additional restrictions on SPIR-V, so it's
4/// often necessary to specify which one applies. `Universal_*` implies an
5/// environment-agnostic SPIR-V.
6///
7/// This enum MUST be kept in sync with the `typedef enum spv_target_env` in
8/// `spirv-tools-sys/spirv-tools/include/spirv-tools/libspirv.h`, it is being
9/// sent across the ffi boundary.
10#[derive(Copy, Clone, Debug, PartialEq)]
11#[repr(C)]
12#[allow(non_camel_case_types, clippy::upper_case_acronyms)]
13pub enum TargetEnv {
14    /// SPIR-V 1.0 latest revision, no other restrictions.
15    Universal_1_0,
16    /// Vulkan 1.0 latest revision.
17    Vulkan_1_0,
18    /// SPIR-V 1.1 latest revision, no other restrictions.
19    Universal_1_1,
20    /// `OpenCL` Full Profile 2.1 latest revision.
21    OpenCL_2_1,
22    /// `OpenCL` Full Profile 2.2 latest revision.
23    OpenCL_2_2,
24    /// OpenGL 4.0 plus `GL_ARB_gl_spirv`, latest revisions.
25    OpenGL_4_0,
26    /// OpenGL 4.1 plus `GL_ARB_gl_spirv`, latest revisions.
27    OpenGL_4_1,
28    /// OpenGL 4.2 plus `GL_ARB_gl_spirv`, latest revisions.
29    OpenGL_4_2,
30    /// OpenGL 4.3 plus `GL_ARB_gl_spirv`, latest revisions.
31    OpenGL_4_3,
32    /// OpenGL 4.5 plus `GL_ARB_gl_spirv`, latest revisions.
33    OpenGL_4_5,
34    /// SPIR-V 1.2, latest revision, no other restrictions.
35    Universal_1_2,
36    /// `OpenCL` Full Profile 1.2 plus `cl_khr_il_program`, latest revision.
37    OpenCL_1_2,
38    /// `OpenCL` Embedded Profile 1.2 plus `cl_khr_il_program`, latest revision.
39    OpenCLEmbedded_1_2,
40    /// `OpenCL` Full Profile 2.0 plus `cl_khr_il_program`, latest revision.
41    OpenCL_2_0,
42    /// `OpenCL` Embedded Profile 2.0 plus `cl_khr_il_program`, latest revision.
43    OpenCLEmbedded_2_0,
44    /// `OpenCL` Embedded Profile 2.1 latest revision.
45    OpenCLEmbedded_2_1,
46    /// `OpenCL` Embedded Profile 2.2 latest revision.
47    OpenCLEmbedded_2_2,
48    /// SPIR-V 1.3 latest revision, no other restrictions.
49    Universal_1_3,
50    /// Vulkan 1.1 latest revision.
51    Vulkan_1_1,
52    /// DEPRECATED, may be removed in the future.
53    WebGPU_0_DEPRECATED,
54    /// SPIR-V 1.4 latest revision, no other restrictions.
55    Universal_1_4,
56    /// Vulkan 1.1 with `VK_KHR_spirv_1_4`, i.e. SPIR-V 1.4 binary.
57    Vulkan_1_1_Spirv_1_4,
58    /// SPIR-V 1.5 latest revision, no other restrictions.
59    Universal_1_5,
60    /// Vulkan 1.2 latest revision.
61    Vulkan_1_2,
62    /// SPIR-V 1.6 latest revision, no other restrictions.
63    Universal_1_6,
64    /// Vulkan 1.3 latest revision.
65    Vulkan_1_3,
66    /// Vulkan 1.4 latest revision.
67    Vulkan_1_4,
68}
69
70impl TargetEnv {
71    /// Returns the `(mayor, minor)` version of spv this enum variant must at least support
72    ///
73    /// The spirv versions for vulkan targets have been pulled from the source of the vulkan spec:
74    /// <https://github.com/KhronosGroup/Vulkan-Docs/blob/main/appendices/spirvenv.adoc?plain=1#L21>
75    pub fn spirv_version(&self) -> (u8, u8) {
76        #[allow(clippy::match_same_arms)]
77        match self {
78            TargetEnv::Universal_1_0 => (1, 0),
79            TargetEnv::Universal_1_1 => (1, 1),
80            TargetEnv::Universal_1_2 => (1, 2),
81            TargetEnv::Universal_1_3 => (1, 3),
82            TargetEnv::Universal_1_4 => (1, 4),
83            TargetEnv::Universal_1_5 => (1, 5),
84            TargetEnv::Universal_1_6 => (1, 6),
85
86            TargetEnv::OpenGL_4_0 => (1, 0),
87            TargetEnv::OpenGL_4_1 => (1, 0),
88            TargetEnv::OpenGL_4_2 => (1, 0),
89            TargetEnv::OpenGL_4_3 => (1, 0),
90            TargetEnv::OpenGL_4_5 => (1, 0),
91
92            TargetEnv::OpenCL_1_2 => (1, 0),
93            TargetEnv::OpenCL_2_0 => (1, 0),
94            TargetEnv::OpenCL_2_1 => (1, 0),
95            TargetEnv::OpenCL_2_2 => (1, 2),
96            TargetEnv::OpenCLEmbedded_1_2 => (1, 0),
97            TargetEnv::OpenCLEmbedded_2_0 => (1, 0),
98            TargetEnv::OpenCLEmbedded_2_1 => (1, 0),
99            TargetEnv::OpenCLEmbedded_2_2 => (1, 2),
100
101            TargetEnv::Vulkan_1_0 => (1, 0),
102            TargetEnv::Vulkan_1_1 => (1, 3),
103            TargetEnv::Vulkan_1_1_Spirv_1_4 => (1, 4),
104            TargetEnv::Vulkan_1_2 => (1, 5),
105            TargetEnv::Vulkan_1_3 => (1, 6),
106            TargetEnv::Vulkan_1_4 => (1, 6),
107
108            TargetEnv::WebGPU_0_DEPRECATED => (1, 3),
109        }
110    }
111}
112
113impl Default for TargetEnv {
114    fn default() -> Self {
115        // This is the default target environment for (AFAICT) all spirv-tools
116        Self::Universal_1_5
117    }
118}
119
120impl std::str::FromStr for TargetEnv {
121    type Err = SpirvResult;
122
123    fn from_str(s: &str) -> Result<Self, Self::Err> {
124        Ok(match s {
125            "vulkan1.1spv1.4" => Self::Vulkan_1_1_Spirv_1_4,
126            "vulkan1.0" => Self::Vulkan_1_0,
127            "vulkan1.1" => Self::Vulkan_1_1,
128            "vulkan1.2" => Self::Vulkan_1_2,
129            "vulkan1.3" => Self::Vulkan_1_3,
130            "vulkan1.4" => Self::Vulkan_1_4,
131            "spv1.0" => Self::Universal_1_0,
132            "spv1.1" => Self::Universal_1_1,
133            "spv1.2" => Self::Universal_1_2,
134            "spv1.3" => Self::Universal_1_3,
135            "spv1.4" => Self::Universal_1_4,
136            "spv1.5" => Self::Universal_1_5,
137            "spv1.6" => Self::Universal_1_6,
138            "opencl1.2embedded" => Self::OpenCLEmbedded_1_2,
139            "opencl1.2" => Self::OpenCL_1_2,
140            "opencl2.0embedded" => Self::OpenCLEmbedded_2_0,
141            "opencl2.0" => Self::OpenCL_2_0,
142            "opencl2.1embedded" => Self::OpenCLEmbedded_2_1,
143            "opencl2.1" => Self::OpenCL_2_1,
144            "opencl2.2embedded" => Self::OpenCLEmbedded_2_2,
145            "opencl2.2" => Self::OpenCL_2_2,
146            "opengl4.0" => Self::OpenGL_4_0,
147            "opengl4.1" => Self::OpenGL_4_1,
148            "opengl4.2" => Self::OpenGL_4_2,
149            "opengl4.3" => Self::OpenGL_4_3,
150            "opengl4.5" => Self::OpenGL_4_5,
151            "webgpu0_DEPRECATED" => Self::WebGPU_0_DEPRECATED,
152            _ => return Err(SpirvResult::InvalidValue),
153        })
154    }
155}
156
157impl fmt::Display for TargetEnv {
158    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
159        f.write_str(match self {
160            Self::Vulkan_1_1_Spirv_1_4 => "vulkan1.1spv1.4",
161            Self::Vulkan_1_0 => "vulkan1.0",
162            Self::Vulkan_1_1 => "vulkan1.1",
163            Self::Vulkan_1_2 => "vulkan1.2",
164            Self::Vulkan_1_3 => "vulkan1.3",
165            Self::Vulkan_1_4 => "vulkan1.4",
166            Self::Universal_1_0 => "spv1.0",
167            Self::Universal_1_1 => "spv1.1",
168            Self::Universal_1_2 => "spv1.2",
169            Self::Universal_1_3 => "spv1.3",
170            Self::Universal_1_4 => "spv1.4",
171            Self::Universal_1_5 => "spv1.5",
172            Self::Universal_1_6 => "spv1.6",
173            Self::OpenCLEmbedded_1_2 => "opencl1.2embedded",
174            Self::OpenCL_1_2 => "opencl1.2",
175            Self::OpenCLEmbedded_2_0 => "opencl2.0embedded",
176            Self::OpenCL_2_0 => "opencl2.0",
177            Self::OpenCLEmbedded_2_1 => "opencl2.1embedded",
178            Self::OpenCL_2_1 => "opencl2.1",
179            Self::OpenCLEmbedded_2_2 => "opencl2.2embedded",
180            Self::OpenCL_2_2 => "opencl2.2",
181            Self::OpenGL_4_0 => "opengl4.0",
182            Self::OpenGL_4_1 => "opengl4.1",
183            Self::OpenGL_4_2 => "opengl4.2",
184            Self::OpenGL_4_3 => "opengl4.3",
185            Self::OpenGL_4_5 => "opengl4.5",
186            Self::WebGPU_0_DEPRECATED => "webgpu0_DEPRECATED",
187        })
188    }
189}
190
191#[derive(Copy, Clone, Debug, PartialEq)]
192#[repr(i32)] // SPV_FORCE_32_BIT_ENUM
193pub enum SpirvResult {
194    Success = 0,
195    Unsupported = 1,
196    EndOfStream = 2,
197    Warning = 3,
198    FailedMatch = 4,
199    /// Success, but signals early termination.
200    RequestedTermination = 5,
201    InternalError = -1,
202    OutOfMemory = -2,
203    InvalidPointer = -3,
204    InvalidBinary = -4,
205    InvalidText = -5,
206    InvalidTable = -6,
207    InvalidValue = -7,
208    InvalidDiagnostic = -8,
209    InvalidLookup = -9,
210    InvalidId = -10,
211    InvalidCfg = -11,
212    InvalidLayout = -12,
213    InvalidCapability = -13,
214    /// Indicates data rules validation failure.
215    InvalidData = -14,
216    MissingExtension = -15,
217    /// Indicates wrong SPIR-V version
218    WrongVersion = -16,
219}
220
221impl fmt::Display for SpirvResult {
222    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
223        #[allow(clippy::enum_glob_use)]
224        use SpirvResult::*;
225
226        match self {
227            Success => f.write_str("success"),
228            Unsupported => f.write_str("unsupported"),
229            EndOfStream => f.write_str("end of stream"),
230            Warning => f.write_str("warning"),
231            FailedMatch => f.write_str("failed match"),
232            RequestedTermination => f.write_str("requested termination"),
233            InternalError => f.write_str("internal error"),
234            OutOfMemory => f.write_str("out of memory"),
235            InvalidPointer => f.write_str("invalid pointer"),
236            InvalidBinary => f.write_str("invalid binary"),
237            InvalidText => f.write_str("invalid text"),
238            InvalidTable => f.write_str("invalid table"),
239            InvalidValue => f.write_str("invalid value"),
240            InvalidDiagnostic => f.write_str("invalid diagnostic"),
241            InvalidLookup => f.write_str("invalid lookup"),
242            InvalidId => f.write_str("invalid id"),
243            InvalidCfg => f.write_str("invalid cfg"),
244            InvalidLayout => f.write_str("invalid layout"),
245            InvalidCapability => f.write_str("invalid capability"),
246            InvalidData => f.write_str("invalid data"),
247            MissingExtension => f.write_str("missing extension"),
248            WrongVersion => f.write_str("wrong SPIR-V version"),
249        }
250    }
251}
252
253impl std::error::Error for SpirvResult {}
254
255#[repr(C)]
256pub struct Binary {
257    pub code: *const u32,
258    pub size: usize,
259}
260
261#[repr(C)]
262pub struct ToolContext {
263    _unused: [u8; 0],
264}
265
266unsafe extern "C" {
267    /// Creates a context object for most of the SPIRV-Tools API.
268    /// Returns null if env is invalid.
269    ///
270    /// See specific API calls for how the target environment is interpeted
271    /// (particularly assembly and validation).
272    #[link_name = "spvContextCreate"]
273    pub fn context_create(env: TargetEnv) -> *mut ToolContext;
274    /// Destroys the given context object.
275    #[link_name = "spvContextDestroy"]
276    pub fn context_destroy(opt: *mut ToolContext);
277
278    /// Frees a binary stream from memory. This is a no-op if binary is a null
279    /// pointer.
280    #[link_name = "spvBinaryDestroy"]
281    pub fn binary_destroy(binary: *mut Binary);
282}