Skip to main content

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