1use std::ffi::c_void;
4use std::ptr::NonNull;
5
6use mtl_foundation::{Referencing, UInteger};
7use mtl_sys::{msg_send_0, msg_send_1, sel};
8
9use crate::enums::{
10 CompileSymbolVisibility, LanguageVersion, LibraryOptimizationLevel, LibraryType,
11 MathFloatingPointFunctions, MathMode,
12};
13use crate::types::Size;
14
15#[repr(transparent)]
19pub struct CompileOptions(pub(crate) NonNull<c_void>);
20
21impl CompileOptions {
22 pub fn new() -> Option<Self> {
26 unsafe {
27 let class = mtl_sys::Class::get("MTLCompileOptions")?;
28 let ptr: *mut c_void = msg_send_0(class.as_ptr(), sel!(alloc));
29 if ptr.is_null() {
30 return None;
31 }
32 let ptr: *mut c_void = msg_send_0(ptr, sel!(init));
33 Self::from_raw(ptr)
34 }
35 }
36
37 #[inline]
43 pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
44 NonNull::new(ptr).map(Self)
45 }
46
47 #[inline]
49 pub fn as_raw(&self) -> *mut c_void {
50 self.0.as_ptr()
51 }
52
53 #[inline]
57 pub fn fast_math_enabled(&self) -> bool {
58 unsafe { msg_send_0(self.as_ptr(), sel!(fastMathEnabled)) }
59 }
60
61 #[inline]
65 pub fn set_fast_math_enabled(&self, enabled: bool) {
66 unsafe {
67 msg_send_1::<(), bool>(self.as_ptr(), sel!(setFastMathEnabled:), enabled);
68 }
69 }
70
71 #[inline]
75 pub fn language_version(&self) -> LanguageVersion {
76 unsafe { msg_send_0(self.as_ptr(), sel!(languageVersion)) }
77 }
78
79 #[inline]
83 pub fn set_language_version(&self, version: LanguageVersion) {
84 unsafe {
85 msg_send_1::<(), LanguageVersion>(self.as_ptr(), sel!(setLanguageVersion:), version);
86 }
87 }
88
89 #[inline]
93 pub fn preserve_invariance(&self) -> bool {
94 unsafe { msg_send_0(self.as_ptr(), sel!(preserveInvariance)) }
95 }
96
97 #[inline]
101 pub fn set_preserve_invariance(&self, preserve: bool) {
102 unsafe {
103 msg_send_1::<(), bool>(self.as_ptr(), sel!(setPreserveInvariance:), preserve);
104 }
105 }
106
107 #[inline]
111 pub fn optimization_level(&self) -> LibraryOptimizationLevel {
112 unsafe { msg_send_0(self.as_ptr(), sel!(optimizationLevel)) }
113 }
114
115 #[inline]
119 pub fn set_optimization_level(&self, level: LibraryOptimizationLevel) {
120 unsafe {
121 msg_send_1::<(), LibraryOptimizationLevel>(
122 self.as_ptr(),
123 sel!(setOptimizationLevel:),
124 level,
125 );
126 }
127 }
128
129 #[inline]
133 pub fn math_mode(&self) -> MathMode {
134 unsafe { msg_send_0(self.as_ptr(), sel!(mathMode)) }
135 }
136
137 #[inline]
141 pub fn set_math_mode(&self, mode: MathMode) {
142 unsafe {
143 msg_send_1::<(), MathMode>(self.as_ptr(), sel!(setMathMode:), mode);
144 }
145 }
146
147 #[inline]
151 pub fn math_floating_point_functions(&self) -> MathFloatingPointFunctions {
152 unsafe { msg_send_0(self.as_ptr(), sel!(mathFloatingPointFunctions)) }
153 }
154
155 #[inline]
159 pub fn set_math_floating_point_functions(&self, funcs: MathFloatingPointFunctions) {
160 unsafe {
161 msg_send_1::<(), MathFloatingPointFunctions>(
162 self.as_ptr(),
163 sel!(setMathFloatingPointFunctions:),
164 funcs,
165 );
166 }
167 }
168
169 #[inline]
173 pub fn compile_symbol_visibility(&self) -> CompileSymbolVisibility {
174 unsafe { msg_send_0(self.as_ptr(), sel!(compileSymbolVisibility)) }
175 }
176
177 #[inline]
181 pub fn set_compile_symbol_visibility(&self, visibility: CompileSymbolVisibility) {
182 unsafe {
183 msg_send_1::<(), CompileSymbolVisibility>(
184 self.as_ptr(),
185 sel!(setCompileSymbolVisibility:),
186 visibility,
187 );
188 }
189 }
190
191 #[inline]
195 pub fn library_type(&self) -> LibraryType {
196 unsafe { msg_send_0(self.as_ptr(), sel!(libraryType)) }
197 }
198
199 #[inline]
203 pub fn set_library_type(&self, lib_type: LibraryType) {
204 unsafe {
205 msg_send_1::<(), LibraryType>(self.as_ptr(), sel!(setLibraryType:), lib_type);
206 }
207 }
208
209 pub fn install_name(&self) -> Option<String> {
213 unsafe {
214 let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(installName));
215 if ptr.is_null() {
216 return None;
217 }
218 let utf8_ptr: *const std::ffi::c_char =
219 mtl_sys::msg_send_0(ptr as *const c_void, sel!(UTF8String));
220 if utf8_ptr.is_null() {
221 return None;
222 }
223 let c_str = std::ffi::CStr::from_ptr(utf8_ptr);
224 Some(c_str.to_string_lossy().into_owned())
225 }
226 }
227
228 pub fn set_install_name(&self, name: &str) {
232 if let Some(ns_name) = mtl_foundation::String::from_str(name) {
233 unsafe {
234 msg_send_1::<(), *const c_void>(
235 self.as_ptr(),
236 sel!(setInstallName:),
237 ns_name.as_ptr(),
238 );
239 }
240 }
241 }
242
243 #[inline]
247 pub fn allow_referencing_undefined_symbols(&self) -> bool {
248 unsafe { msg_send_0(self.as_ptr(), sel!(allowReferencingUndefinedSymbols)) }
249 }
250
251 #[inline]
255 pub fn set_allow_referencing_undefined_symbols(&self, allow: bool) {
256 unsafe {
257 msg_send_1::<(), bool>(
258 self.as_ptr(),
259 sel!(setAllowReferencingUndefinedSymbols:),
260 allow,
261 );
262 }
263 }
264
265 #[inline]
269 pub fn enable_logging(&self) -> bool {
270 unsafe { msg_send_0(self.as_ptr(), sel!(enableLogging)) }
271 }
272
273 #[inline]
277 pub fn set_enable_logging(&self, enable: bool) {
278 unsafe {
279 msg_send_1::<(), bool>(self.as_ptr(), sel!(setEnableLogging:), enable);
280 }
281 }
282
283 #[inline]
287 pub fn max_total_threads_per_threadgroup(&self) -> UInteger {
288 unsafe { msg_send_0(self.as_ptr(), sel!(maxTotalThreadsPerThreadgroup)) }
289 }
290
291 #[inline]
295 pub fn set_max_total_threads_per_threadgroup(&self, count: UInteger) {
296 unsafe {
297 msg_send_1::<(), UInteger>(
298 self.as_ptr(),
299 sel!(setMaxTotalThreadsPerThreadgroup:),
300 count,
301 );
302 }
303 }
304
305 #[inline]
309 pub fn required_threads_per_threadgroup(&self) -> Size {
310 unsafe { msg_send_0(self.as_ptr(), sel!(requiredThreadsPerThreadgroup)) }
311 }
312
313 #[inline]
317 pub fn set_required_threads_per_threadgroup(&self, size: Size) {
318 unsafe {
319 msg_send_1::<(), Size>(self.as_ptr(), sel!(setRequiredThreadsPerThreadgroup:), size);
320 }
321 }
322
323 pub fn preprocessor_macros_raw(&self) -> *mut c_void {
330 unsafe { msg_send_0(self.as_ptr(), sel!(preprocessorMacros)) }
331 }
332
333 pub unsafe fn set_preprocessor_macros_raw(&self, dict: *const c_void) {
343 unsafe {
344 msg_send_1::<(), *const c_void>(self.as_ptr(), sel!(setPreprocessorMacros:), dict);
345 }
346 }
347}
348
349impl Default for CompileOptions {
350 fn default() -> Self {
351 Self::new().expect("failed to create compile options")
352 }
353}
354
355impl Clone for CompileOptions {
356 fn clone(&self) -> Self {
357 unsafe {
358 let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(copy));
359 Self::from_raw(ptr).expect("failed to copy compile options")
360 }
361 }
362}
363
364impl Drop for CompileOptions {
365 fn drop(&mut self) {
366 unsafe {
367 msg_send_0::<()>(self.as_ptr(), sel!(release));
368 }
369 }
370}
371
372impl Referencing for CompileOptions {
373 #[inline]
374 fn as_ptr(&self) -> *const c_void {
375 self.0.as_ptr()
376 }
377}
378
379unsafe impl Send for CompileOptions {}
380unsafe impl Sync for CompileOptions {}