1 use mesa_rust_gen::*; 2 use mesa_rust_util::bitset; 3 use mesa_rust_util::offset_of; 4 5 use std::convert::TryInto; 6 use std::ffi::c_void; 7 use std::ffi::CString; 8 use std::marker::PhantomData; 9 use std::ptr; 10 use std::ptr::NonNull; 11 use std::slice; 12 13 pub struct ExecListIter<'a, T> { 14 n: &'a mut exec_node, 15 offset: usize, 16 _marker: PhantomData<T>, 17 } 18 19 impl<'a, T> ExecListIter<'a, T> { new(l: &'a mut exec_list, offset: usize) -> Self20 fn new(l: &'a mut exec_list, offset: usize) -> Self { 21 Self { 22 n: &mut l.head_sentinel, 23 offset: offset, 24 _marker: PhantomData, 25 } 26 } 27 } 28 29 impl<'a, T: 'a> Iterator for ExecListIter<'a, T> { 30 type Item = &'a mut T; 31 next(&mut self) -> Option<Self::Item>32 fn next(&mut self) -> Option<Self::Item> { 33 self.n = unsafe { &mut *self.n.next }; 34 if self.n.next.is_null() { 35 None 36 } else { 37 let t: *mut c_void = (self.n as *mut exec_node).cast(); 38 Some(unsafe { &mut *(t.sub(self.offset).cast()) }) 39 } 40 } 41 } 42 43 #[macro_export] 44 #[cfg(debug_assertions)] 45 macro_rules! nir_pass_impl { 46 ($nir:ident, $pass:ident, $func:ident $(,$arg:expr)* $(,)?) => { 47 { 48 let func_str = ::std::stringify!($func); 49 let func_cstr = ::std::ffi::CString::new(func_str).unwrap(); 50 let res = if unsafe { should_skip_nir(func_cstr.as_ptr()) } { 51 println!("skipping {}", func_str); 52 false 53 } else { 54 $nir.metadata_set_validation_flag(); 55 if $nir.should_print() { 56 println!("{}", func_str); 57 } 58 if $nir.$pass($func $(,$arg)*) { 59 $nir.validate(&format!("after {} in {}:{}", func_str, file!(), line!())); 60 if $nir.should_print() { 61 $nir.print(); 62 } 63 $nir.metadata_check_validation_flag(); 64 true 65 } else { 66 false 67 } 68 }; 69 70 // SAFETY: mutable static can't be read safely, but this value isn't going to change 71 let ndebug = unsafe { nir_debug }; 72 if ndebug & NIR_DEBUG_CLONE != 0 { 73 $nir.validate_clone(); 74 } 75 76 if ndebug & NIR_DEBUG_SERIALIZE != 0 { 77 $nir.validate_serialize_deserialize(); 78 } 79 80 res 81 } 82 }; 83 } 84 85 #[macro_export] 86 #[cfg(not(debug_assertions))] 87 macro_rules! nir_pass_impl { 88 ($nir:ident, $pass:ident, $func:ident $(,$arg:expr)* $(,)?) => { 89 $nir.$pass($func $(,$arg)*) 90 }; 91 } 92 93 #[macro_export] 94 macro_rules! nir_pass { 95 ($nir:ident, $func:ident $(,)?) => { 96 $crate::nir_pass_impl!($nir, pass0, $func) 97 }; 98 99 ($nir:ident, $func:ident, $a:expr $(,)?) => { 100 $crate::nir_pass_impl!($nir, pass1, $func, $a) 101 }; 102 103 ($nir:ident, $func:ident, $a:expr, $b:expr $(,)?) => { 104 $crate::nir_pass_impl!($nir, pass2, $func, $a, $b) 105 }; 106 107 ($nir:ident, $func:ident, $a:expr, $b:expr, $c:expr $(,)?) => { 108 $crate::nir_pass_impl!($nir, pass3, $func, $a, $b, $c) 109 }; 110 } 111 112 pub struct NirPrintfInfo { 113 count: usize, 114 printf_info: *mut u_printf_info, 115 } 116 117 // SAFETY: `u_printf_info` is considered immutable 118 unsafe impl Send for NirPrintfInfo {} 119 unsafe impl Sync for NirPrintfInfo {} 120 121 impl NirPrintfInfo { u_printf(&self, buf: &[u8])122 pub fn u_printf(&self, buf: &[u8]) { 123 unsafe { 124 u_printf( 125 stdout_ptr(), 126 buf.as_ptr().cast(), 127 buf.len(), 128 self.printf_info.cast(), 129 self.count as u32, 130 ); 131 } 132 } 133 } 134 135 impl Drop for NirPrintfInfo { drop(&mut self)136 fn drop(&mut self) { 137 unsafe { 138 ralloc_free(self.printf_info.cast()); 139 }; 140 } 141 } 142 143 pub struct NirShader { 144 nir: NonNull<nir_shader>, 145 } 146 147 // SAFETY: It's safe to share a nir_shader between threads. 148 unsafe impl Send for NirShader {} 149 150 // SAFETY: We do not allow interior mutability with &NirShader 151 unsafe impl Sync for NirShader {} 152 153 impl NirShader { new(nir: *mut nir_shader) -> Option<Self>154 pub fn new(nir: *mut nir_shader) -> Option<Self> { 155 NonNull::new(nir).map(|nir| Self { nir: nir }) 156 } 157 deserialize( input: &mut &[u8], len: usize, options: *const nir_shader_compiler_options, ) -> Option<Self>158 pub fn deserialize( 159 input: &mut &[u8], 160 len: usize, 161 options: *const nir_shader_compiler_options, 162 ) -> Option<Self> { 163 let mut reader = blob_reader::default(); 164 165 let (bin, rest) = input.split_at(len); 166 *input = rest; 167 168 unsafe { 169 blob_reader_init(&mut reader, bin.as_ptr().cast(), len); 170 Self::new(nir_deserialize(ptr::null_mut(), options, &mut reader)) 171 } 172 } 173 serialize(&self) -> Vec<u8>174 pub fn serialize(&self) -> Vec<u8> { 175 let mut blob = blob::default(); 176 unsafe { 177 blob_init(&mut blob); 178 nir_serialize(&mut blob, self.nir.as_ptr(), false); 179 let res = slice::from_raw_parts(blob.data, blob.size).to_vec(); 180 blob_finish(&mut blob); 181 res 182 } 183 } 184 print(&self)185 pub fn print(&self) { 186 unsafe { nir_print_shader(self.nir.as_ptr(), stderr_ptr()) }; 187 } 188 get_nir(&self) -> *mut nir_shader189 pub fn get_nir(&self) -> *mut nir_shader { 190 self.nir.as_ptr() 191 } 192 dup_for_driver(&self) -> *mut nir_shader193 pub fn dup_for_driver(&self) -> *mut nir_shader { 194 unsafe { nir_shader_clone(ptr::null_mut(), self.nir.as_ptr()) } 195 } 196 sweep_mem(&mut self)197 pub fn sweep_mem(&mut self) { 198 unsafe { nir_sweep(self.nir.as_ptr()) } 199 } 200 pass0<R>(&mut self, pass: unsafe extern "C" fn(*mut nir_shader) -> R) -> R201 pub fn pass0<R>(&mut self, pass: unsafe extern "C" fn(*mut nir_shader) -> R) -> R { 202 unsafe { pass(self.nir.as_ptr()) } 203 } 204 pass1<R, A>( &mut self, pass: unsafe extern "C" fn(*mut nir_shader, a: A) -> R, a: A, ) -> R205 pub fn pass1<R, A>( 206 &mut self, 207 pass: unsafe extern "C" fn(*mut nir_shader, a: A) -> R, 208 a: A, 209 ) -> R { 210 unsafe { pass(self.nir.as_ptr(), a) } 211 } 212 pass2<R, A, B>( &mut self, pass: unsafe extern "C" fn(*mut nir_shader, a: A, b: B) -> R, a: A, b: B, ) -> R213 pub fn pass2<R, A, B>( 214 &mut self, 215 pass: unsafe extern "C" fn(*mut nir_shader, a: A, b: B) -> R, 216 a: A, 217 b: B, 218 ) -> R { 219 unsafe { pass(self.nir.as_ptr(), a, b) } 220 } 221 pass3<R, A, B, C>( &mut self, pass: unsafe extern "C" fn(*mut nir_shader, a: A, b: B, c: C) -> R, a: A, b: B, c: C, ) -> R222 pub fn pass3<R, A, B, C>( 223 &mut self, 224 pass: unsafe extern "C" fn(*mut nir_shader, a: A, b: B, c: C) -> R, 225 a: A, 226 b: B, 227 c: C, 228 ) -> R { 229 unsafe { pass(self.nir.as_ptr(), a, b, c) } 230 } 231 232 #[cfg(debug_assertions)] metadata_check_validation_flag(&self)233 pub fn metadata_check_validation_flag(&self) { 234 unsafe { nir_metadata_check_validation_flag(self.nir.as_ptr()) } 235 } 236 237 #[cfg(debug_assertions)] metadata_set_validation_flag(&mut self)238 pub fn metadata_set_validation_flag(&mut self) { 239 unsafe { nir_metadata_set_validation_flag(self.nir.as_ptr()) } 240 } 241 242 #[cfg(debug_assertions)] validate(&self, when: &str)243 pub fn validate(&self, when: &str) { 244 let cstr = CString::new(when).unwrap(); 245 unsafe { nir_validate_shader(self.nir.as_ptr(), cstr.as_ptr()) } 246 } 247 should_print(&self) -> bool248 pub fn should_print(&self) -> bool { 249 unsafe { should_print_nir(self.nir.as_ptr()) } 250 } 251 validate_serialize_deserialize(&mut self)252 pub fn validate_serialize_deserialize(&mut self) { 253 unsafe { nir_shader_serialize_deserialize(self.nir.as_ptr()) } 254 } 255 validate_clone(&mut self)256 pub fn validate_clone(&mut self) { 257 unsafe { 258 let nir_ptr = self.nir.as_ptr(); 259 let clone = nir_shader_clone(ralloc_parent(nir_ptr.cast()), nir_ptr); 260 nir_shader_replace(nir_ptr, clone) 261 } 262 } 263 entrypoint(&self) -> *mut nir_function_impl264 pub fn entrypoint(&self) -> *mut nir_function_impl { 265 unsafe { nir_shader_get_entrypoint(self.nir.as_ptr()) } 266 } 267 structurize(&mut self)268 pub fn structurize(&mut self) { 269 nir_pass!(self, nir_lower_goto_ifs); 270 nir_pass!(self, nir_opt_dead_cf); 271 } 272 inline(&mut self, libclc: &NirShader)273 pub fn inline(&mut self, libclc: &NirShader) { 274 nir_pass!( 275 self, 276 nir_lower_variable_initializers, 277 nir_variable_mode::nir_var_function_temp, 278 ); 279 nir_pass!(self, nir_lower_returns); 280 nir_pass!(self, nir_link_shader_functions, libclc.nir.as_ptr()); 281 nir_pass!(self, nir_inline_functions); 282 } 283 gather_info(&mut self)284 pub fn gather_info(&mut self) { 285 unsafe { nir_shader_gather_info(self.nir.as_ptr(), self.entrypoint()) } 286 } 287 remove_non_entrypoints(&mut self)288 pub fn remove_non_entrypoints(&mut self) { 289 unsafe { nir_remove_non_entrypoints(self.nir.as_ptr()) }; 290 } 291 cleanup_functions(&mut self)292 pub fn cleanup_functions(&mut self) { 293 unsafe { nir_cleanup_functions(self.nir.as_ptr()) }; 294 } 295 variables(&mut self) -> ExecListIter<nir_variable>296 pub fn variables(&mut self) -> ExecListIter<nir_variable> { 297 ExecListIter::new( 298 &mut unsafe { self.nir.as_mut() }.variables, 299 offset_of!(nir_variable, node), 300 ) 301 } 302 num_images(&self) -> u8303 pub fn num_images(&self) -> u8 { 304 unsafe { (*self.nir.as_ptr()).info.num_images } 305 } 306 num_textures(&self) -> u8307 pub fn num_textures(&self) -> u8 { 308 unsafe { (*self.nir.as_ptr()).info.num_textures } 309 } 310 reset_scratch_size(&mut self)311 pub fn reset_scratch_size(&mut self) { 312 unsafe { 313 (*self.nir.as_ptr()).scratch_size = 0; 314 } 315 } 316 scratch_size(&self) -> u32317 pub fn scratch_size(&self) -> u32 { 318 unsafe { (*self.nir.as_ptr()).scratch_size } 319 } 320 reset_shared_size(&mut self)321 pub fn reset_shared_size(&mut self) { 322 unsafe { 323 (*self.nir.as_ptr()).info.shared_size = 0; 324 } 325 } shared_size(&self) -> u32326 pub fn shared_size(&self) -> u32 { 327 unsafe { (*self.nir.as_ptr()).info.shared_size } 328 } 329 workgroup_size(&self) -> [u16; 3]330 pub fn workgroup_size(&self) -> [u16; 3] { 331 unsafe { (*self.nir.as_ptr()).info.workgroup_size } 332 } 333 subgroup_size(&self) -> u8334 pub fn subgroup_size(&self) -> u8 { 335 let subgroup_size = unsafe { (*self.nir.as_ptr()).info.subgroup_size }; 336 let valid_subgroup_sizes = [ 337 gl_subgroup_size::SUBGROUP_SIZE_REQUIRE_8, 338 gl_subgroup_size::SUBGROUP_SIZE_REQUIRE_16, 339 gl_subgroup_size::SUBGROUP_SIZE_REQUIRE_32, 340 gl_subgroup_size::SUBGROUP_SIZE_REQUIRE_64, 341 gl_subgroup_size::SUBGROUP_SIZE_REQUIRE_128, 342 ]; 343 344 if valid_subgroup_sizes.contains(&subgroup_size) { 345 subgroup_size as u8 346 } else { 347 0 348 } 349 } 350 num_subgroups(&self) -> u8351 pub fn num_subgroups(&self) -> u8 { 352 unsafe { (*self.nir.as_ptr()).info.num_subgroups } 353 } 354 set_workgroup_size_variable_if_zero(&mut self)355 pub fn set_workgroup_size_variable_if_zero(&mut self) { 356 let nir = self.nir.as_ptr(); 357 unsafe { 358 (*nir) 359 .info 360 .set_workgroup_size_variable((*nir).info.workgroup_size[0] == 0); 361 } 362 } 363 set_has_variable_shared_mem(&mut self, val: bool)364 pub fn set_has_variable_shared_mem(&mut self, val: bool) { 365 unsafe { 366 self.nir 367 .as_mut() 368 .info 369 .anon_1 370 .cs 371 .set_has_variable_shared_mem(val) 372 } 373 } 374 variables_with_mode( &mut self, mode: nir_variable_mode, ) -> impl Iterator<Item = &mut nir_variable>375 pub fn variables_with_mode( 376 &mut self, 377 mode: nir_variable_mode, 378 ) -> impl Iterator<Item = &mut nir_variable> { 379 self.variables() 380 .filter(move |v| v.data.mode() & mode.0 != 0) 381 } 382 extract_constant_initializers(&mut self)383 pub fn extract_constant_initializers(&mut self) { 384 let nir = self.nir.as_ptr(); 385 unsafe { 386 if (*nir).constant_data_size > 0 { 387 assert!((*nir).constant_data.is_null()); 388 (*nir).constant_data = rzalloc_size(nir.cast(), (*nir).constant_data_size as usize); 389 nir_gather_explicit_io_initializers( 390 nir, 391 (*nir).constant_data, 392 (*nir).constant_data_size as usize, 393 nir_variable_mode::nir_var_mem_constant, 394 ); 395 } 396 } 397 } 398 has_constant(&self) -> bool399 pub fn has_constant(&self) -> bool { 400 unsafe { 401 !self.nir.as_ref().constant_data.is_null() && self.nir.as_ref().constant_data_size > 0 402 } 403 } 404 has_printf(&self) -> bool405 pub fn has_printf(&self) -> bool { 406 unsafe { 407 !self.nir.as_ref().printf_info.is_null() && self.nir.as_ref().printf_info_count != 0 408 } 409 } 410 take_printf_info(&mut self) -> Option<NirPrintfInfo>411 pub fn take_printf_info(&mut self) -> Option<NirPrintfInfo> { 412 let nir = unsafe { self.nir.as_mut() }; 413 414 let info = nir.printf_info; 415 if info.is_null() { 416 return None; 417 } 418 let count = nir.printf_info_count as usize; 419 420 unsafe { 421 ralloc_steal(ptr::null(), info.cast()); 422 423 for i in 0..count { 424 ralloc_steal(info.cast(), (*info.add(i)).arg_sizes.cast()); 425 ralloc_steal(info.cast(), (*info.add(i)).strings.cast()); 426 } 427 }; 428 429 let result = Some(NirPrintfInfo { 430 count: count, 431 printf_info: info, 432 }); 433 434 nir.printf_info_count = 0; 435 nir.printf_info = ptr::null_mut(); 436 437 result 438 } 439 get_constant_buffer(&self) -> &[u8]440 pub fn get_constant_buffer(&self) -> &[u8] { 441 unsafe { 442 let nir = self.nir.as_ref(); 443 slice::from_raw_parts(nir.constant_data.cast(), nir.constant_data_size as usize) 444 } 445 } 446 preserve_fp16_denorms(&mut self)447 pub fn preserve_fp16_denorms(&mut self) { 448 unsafe { 449 self.nir.as_mut().info.float_controls_execution_mode |= 450 float_controls::FLOAT_CONTROLS_DENORM_PRESERVE_FP16 as u32; 451 } 452 } 453 set_fp_rounding_mode_rtne(&mut self)454 pub fn set_fp_rounding_mode_rtne(&mut self) { 455 unsafe { 456 self.nir.as_mut().info.float_controls_execution_mode |= 457 float_controls::FLOAT_CONTROLS_ROUNDING_MODE_RTE_FP16 as u32 458 | float_controls::FLOAT_CONTROLS_ROUNDING_MODE_RTE_FP32 as u32 459 | float_controls::FLOAT_CONTROLS_ROUNDING_MODE_RTE_FP64 as u32; 460 } 461 } 462 reads_sysval(&self, sysval: gl_system_value) -> bool463 pub fn reads_sysval(&self, sysval: gl_system_value) -> bool { 464 let nir = unsafe { self.nir.as_ref() }; 465 bitset::test_bit(&nir.info.system_values_read, sysval as u32) 466 } 467 add_var( &mut self, mode: nir_variable_mode, glsl_type: *const glsl_type, loc: usize, name: &str, )468 pub fn add_var( 469 &mut self, 470 mode: nir_variable_mode, 471 glsl_type: *const glsl_type, 472 loc: usize, 473 name: &str, 474 ) { 475 let name = CString::new(name).unwrap(); 476 unsafe { 477 let var = nir_variable_create(self.nir.as_ptr(), mode, glsl_type, name.as_ptr()); 478 (*var).data.location = loc.try_into().unwrap(); 479 } 480 } 481 } 482 483 impl Drop for NirShader { drop(&mut self)484 fn drop(&mut self) { 485 unsafe { ralloc_free(self.nir.as_ptr().cast()) }; 486 } 487 } 488