|
| 1 | +use std::fmt; |
| 2 | + |
1 | 3 | /// Certain target environments impose additional restrictions on SPIR-V, so it's
|
2 | 4 | /// often necessary to specify which one applies. `Universal_*` implies an
|
3 | 5 | /// environment-agnostic SPIR-V.
|
|
11 | 13 | /// SPV_ENV_VULKAN_1_2 -> SPIR-V 1.5
|
12 | 14 | ///
|
13 | 15 | /// Consult the description of API entry points for specific rules.
|
14 |
| -#[derive(Copy, Clone, Debug)] |
| 16 | +#[derive(Copy, Clone, Debug, PartialEq)] |
15 | 17 | #[repr(C)]
|
16 | 18 | #[allow(non_camel_case_types)]
|
17 | 19 | pub enum TargetEnv {
|
@@ -65,14 +67,176 @@ pub enum TargetEnv {
|
65 | 67 | Vulkan_1_2,
|
66 | 68 | }
|
67 | 69 |
|
| 70 | +impl Default for TargetEnv { |
| 71 | + fn default() -> Self { |
| 72 | + // This is the default target environment for (AFAICT) all spirv-tools |
| 73 | + Self::Universal_1_5 |
| 74 | + } |
| 75 | +} |
| 76 | + |
| 77 | +impl std::str::FromStr for TargetEnv { |
| 78 | + type Err = SpirvResult; |
| 79 | + |
| 80 | + fn from_str(s: &str) -> Result<Self, Self::Err> { |
| 81 | + Ok(match s { |
| 82 | + "vulkan1.1spv1.4" => Self::Vulkan_1_1_Spirv_1_4, |
| 83 | + "vulkan1.0" => Self::Vulkan_1_0, |
| 84 | + "vulkan1.1" => Self::Vulkan_1_1, |
| 85 | + "vulkan1.2" => Self::Vulkan_1_2, |
| 86 | + "spv1.0" => Self::Universal_1_0, |
| 87 | + "spv1.1" => Self::Universal_1_1, |
| 88 | + "spv1.2" => Self::Universal_1_2, |
| 89 | + "spv1.3" => Self::Universal_1_3, |
| 90 | + "spv1.4" => Self::Universal_1_4, |
| 91 | + "spv1.5" => Self::Universal_1_5, |
| 92 | + "opencl1.2embedded" => Self::OpenCLEmbedded_1_2, |
| 93 | + "opencl1.2" => Self::OpenCL_1_2, |
| 94 | + "opencl2.0embedded" => Self::OpenCLEmbedded_2_0, |
| 95 | + "opencl2.0" => Self::OpenCL_2_0, |
| 96 | + "opencl2.1embedded" => Self::OpenCLEmbedded_2_1, |
| 97 | + "opencl2.1" => Self::OpenCL_2_1, |
| 98 | + "opencl2.2embedded" => Self::OpenCLEmbedded_2_2, |
| 99 | + "opencl2.2" => Self::OpenCL_2_2, |
| 100 | + "opengl4.0" => Self::OpenGL_4_0, |
| 101 | + "opengl4.1" => Self::OpenGL_4_1, |
| 102 | + "opengl4.2" => Self::OpenGL_4_2, |
| 103 | + "opengl4.3" => Self::OpenGL_4_3, |
| 104 | + "opengl4.5" => Self::OpenGL_4_5, |
| 105 | + "webgpu0" => Self::WebGPU_0, |
| 106 | + _ => return Err(SpirvResult::InvalidValue), |
| 107 | + }) |
| 108 | + } |
| 109 | +} |
| 110 | + |
| 111 | +impl fmt::Display for TargetEnv { |
| 112 | + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 113 | + f.write_str(match self { |
| 114 | + Self::Vulkan_1_1_Spirv_1_4 => "vulkan1.1spv1.4", |
| 115 | + Self::Vulkan_1_0 => "vulkan1.0", |
| 116 | + Self::Vulkan_1_1 => "vulkan1.1", |
| 117 | + Self::Vulkan_1_2 => "vulkan1.2", |
| 118 | + Self::Universal_1_0 => "spv1.0", |
| 119 | + Self::Universal_1_1 => "spv1.1", |
| 120 | + Self::Universal_1_2 => "spv1.2", |
| 121 | + Self::Universal_1_3 => "spv1.3", |
| 122 | + Self::Universal_1_4 => "spv1.4", |
| 123 | + Self::Universal_1_5 => "spv1.5", |
| 124 | + Self::OpenCLEmbedded_1_2 => "opencl1.2embedded", |
| 125 | + Self::OpenCL_1_2 => "opencl1.2", |
| 126 | + Self::OpenCLEmbedded_2_0 => "opencl2.0embedded", |
| 127 | + Self::OpenCL_2_0 => "opencl2.0", |
| 128 | + Self::OpenCLEmbedded_2_1 => "opencl2.1embedded", |
| 129 | + Self::OpenCL_2_1 => "opencl2.1", |
| 130 | + Self::OpenCLEmbedded_2_2 => "opencl2.2embedded", |
| 131 | + Self::OpenCL_2_2 => "opencl2.2", |
| 132 | + Self::OpenGL_4_0 => "opengl4.0", |
| 133 | + Self::OpenGL_4_1 => "opengl4.1", |
| 134 | + Self::OpenGL_4_2 => "opengl4.2", |
| 135 | + Self::OpenGL_4_3 => "opengl4.3", |
| 136 | + Self::OpenGL_4_5 => "opengl4.5", |
| 137 | + Self::WebGPU_0 => "webgpu0", |
| 138 | + }) |
| 139 | + } |
| 140 | +} |
| 141 | + |
| 142 | +#[derive(Copy, Clone, Debug, PartialEq)] |
| 143 | +#[repr(i32)] // SPV_FORCE_32_BIT_ENUM |
| 144 | +pub enum SpirvResult { |
| 145 | + Success = 0, |
| 146 | + Unsupported = 1, |
| 147 | + EndOfStream = 2, |
| 148 | + Warning = 3, |
| 149 | + FailedMatch = 4, |
| 150 | + /// Success, but signals early termination. |
| 151 | + RequestedTermination = 5, |
| 152 | + InternalError = -1, |
| 153 | + OutOfMemory = -2, |
| 154 | + InvalidPointer = -3, |
| 155 | + InvalidBinary = -4, |
| 156 | + InvalidText = -5, |
| 157 | + InvalidTable = -6, |
| 158 | + InvalidValue = -7, |
| 159 | + InvalidDiagnostic = -8, |
| 160 | + InvalidLookup = -9, |
| 161 | + InvalidId = -10, |
| 162 | + InvalidCfg = -11, |
| 163 | + InvalidLayout = -12, |
| 164 | + InvalidCapability = -13, |
| 165 | + /// Indicates data rules validation failure. |
| 166 | + InvalidData = -14, |
| 167 | + MissingExtension = -15, |
| 168 | + /// Indicates wrong SPIR-V version |
| 169 | + WrongVersion = -16, |
| 170 | +} |
| 171 | + |
| 172 | +impl fmt::Display for SpirvResult { |
| 173 | + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 174 | + use SpirvResult::*; |
| 175 | + |
| 176 | + match self { |
| 177 | + Success => f.write_str("success"), |
| 178 | + Unsupported => f.write_str("unsupported"), |
| 179 | + EndOfStream => f.write_str("end of stream"), |
| 180 | + Warning => f.write_str("warning"), |
| 181 | + FailedMatch => f.write_str("failed match"), |
| 182 | + RequestedTermination => f.write_str("requested termination"), |
| 183 | + InternalError => f.write_str("internal error"), |
| 184 | + OutOfMemory => f.write_str("out of memory"), |
| 185 | + InvalidPointer => f.write_str("invalid pointer"), |
| 186 | + InvalidBinary => f.write_str("invalid binary"), |
| 187 | + InvalidText => f.write_str("invalid text"), |
| 188 | + InvalidTable => f.write_str("invalid table"), |
| 189 | + InvalidValue => f.write_str("invalid value"), |
| 190 | + InvalidDiagnostic => f.write_str("invalid diagnostic"), |
| 191 | + InvalidLookup => f.write_str("invalid lookup"), |
| 192 | + InvalidId => f.write_str("invalid id"), |
| 193 | + InvalidCfg => f.write_str("invalid cfg"), |
| 194 | + InvalidLayout => f.write_str("invalid layout"), |
| 195 | + InvalidCapability => f.write_str("invalid capability"), |
| 196 | + InvalidData => f.write_str("invalid data"), |
| 197 | + MissingExtension => f.write_str("missing extension"), |
| 198 | + WrongVersion => f.write_str("wrong SPIR-V version"), |
| 199 | + } |
| 200 | + } |
| 201 | +} |
| 202 | + |
| 203 | +impl std::error::Error for SpirvResult {} |
| 204 | + |
68 | 205 | #[cfg(feature = "tools")]
|
69 | 206 | #[repr(C)]
|
70 |
| -pub struct Tool { |
| 207 | +pub struct ToolContext { |
71 | 208 | _unused: [u8; 0],
|
72 | 209 | }
|
73 | 210 |
|
| 211 | +#[repr(C)] |
| 212 | +pub struct Position { |
| 213 | + pub line: usize, |
| 214 | + pub column: usize, |
| 215 | + pub index: usize, |
| 216 | +} |
| 217 | + |
| 218 | +#[repr(C)] |
| 219 | +pub struct Diagnostic { |
| 220 | + pub position: Position, |
| 221 | + pub error: *const std::os::raw::c_char, |
| 222 | + pub is_text_source: bool, |
| 223 | +} |
| 224 | + |
74 | 225 | #[cfg(feature = "tools")]
|
75 | 226 | extern "C" {
|
76 |
| - pub fn tool_create(env: TargetEnv) -> *mut Tool; |
77 |
| - pub fn tool_destroy(opt: *mut Tool); |
| 227 | + /// Creates a context object for most of the SPIRV-Tools API. |
| 228 | + /// Returns null if env is invalid. |
| 229 | + /// |
| 230 | + /// See specific API calls for how the target environment is interpeted |
| 231 | + /// (particularly assembly and validation). |
| 232 | + #[link_name = "spvContextCreate"] |
| 233 | + pub fn context_create(env: TargetEnv) -> *mut ToolContext; |
| 234 | + /// Destroys the given context object. |
| 235 | + #[link_name = "spvContextDestroy"] |
| 236 | + pub fn context_destroy(opt: *mut ToolContext); |
| 237 | + |
| 238 | + /// Destroys a diagnostic object. This is a no-op if diagnostic is a null |
| 239 | + /// pointer. |
| 240 | + #[link_name = "spvDiagnosticDestroy"] |
| 241 | + pub fn diagnostic_destroy(diag: *mut Diagnostic); |
78 | 242 | }
|
0 commit comments