• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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