xref: /aosp_15_r20/external/mesa3d/src/gallium/frontends/rusticl/mesa/pipe/screen.rs (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 use crate::compiler::nir::NirShader;
2 use crate::pipe::context::*;
3 use crate::pipe::device::*;
4 use crate::pipe::resource::*;
5 use crate::util::disk_cache::*;
6 
7 use mesa_rust_gen::*;
8 use mesa_rust_util::has_required_feature;
9 use mesa_rust_util::ptr::ThreadSafeCPtr;
10 
11 use std::convert::TryInto;
12 use std::ffi::CStr;
13 use std::mem::size_of;
14 use std::os::raw::c_schar;
15 use std::os::raw::c_uchar;
16 use std::os::raw::c_void;
17 use std::ptr;
18 use std::sync::Arc;
19 
20 #[derive(PartialEq)]
21 pub struct PipeScreen {
22     ldev: PipeLoaderDevice,
23     screen: ThreadSafeCPtr<pipe_screen>,
24 }
25 
26 pub const UUID_SIZE: usize = PIPE_UUID_SIZE as usize;
27 const LUID_SIZE: usize = PIPE_LUID_SIZE as usize;
28 
29 // until we have a better solution
30 pub trait ComputeParam<T> {
compute_param(&self, cap: pipe_compute_cap) -> T31     fn compute_param(&self, cap: pipe_compute_cap) -> T;
32 }
33 
34 macro_rules! compute_param_impl {
35     ($ty:ty) => {
36         impl ComputeParam<$ty> for PipeScreen {
37             fn compute_param(&self, cap: pipe_compute_cap) -> $ty {
38                 let size = self.compute_param_wrapped(cap, ptr::null_mut());
39                 let mut d = [0; size_of::<$ty>()];
40                 if size == 0 {
41                     return Default::default();
42                 }
43                 assert_eq!(size as usize, d.len());
44                 self.compute_param_wrapped(cap, d.as_mut_ptr().cast());
45                 <$ty>::from_ne_bytes(d)
46             }
47         }
48     };
49 }
50 
51 compute_param_impl!(u32);
52 compute_param_impl!(u64);
53 
54 impl ComputeParam<Vec<u64>> for PipeScreen {
compute_param(&self, cap: pipe_compute_cap) -> Vec<u64>55     fn compute_param(&self, cap: pipe_compute_cap) -> Vec<u64> {
56         let size = self.compute_param_wrapped(cap, ptr::null_mut());
57         let elems = (size / 8) as usize;
58 
59         let mut res: Vec<u64> = Vec::new();
60         let mut d: Vec<u8> = vec![0; size as usize];
61 
62         self.compute_param_wrapped(cap, d.as_mut_ptr().cast());
63         for i in 0..elems {
64             let offset = i * 8;
65             let slice = &d[offset..offset + 8];
66             res.push(u64::from_ne_bytes(slice.try_into().expect("")));
67         }
68         res
69     }
70 }
71 
72 #[derive(Clone, Copy, PartialEq, Eq)]
73 pub enum ResourceType {
74     Normal,
75     Staging,
76 }
77 
78 impl ResourceType {
apply(&self, tmpl: &mut pipe_resource)79     fn apply(&self, tmpl: &mut pipe_resource) {
80         match self {
81             Self::Staging => {
82                 tmpl.set_usage(pipe_resource_usage::PIPE_USAGE_STAGING);
83                 tmpl.flags |= PIPE_RESOURCE_FLAG_MAP_PERSISTENT | PIPE_RESOURCE_FLAG_MAP_COHERENT;
84                 tmpl.bind |= PIPE_BIND_LINEAR;
85             }
86             Self::Normal => {}
87         }
88     }
89 }
90 
91 impl PipeScreen {
new(ldev: PipeLoaderDevice, screen: *mut pipe_screen) -> Option<Self>92     pub(super) fn new(ldev: PipeLoaderDevice, screen: *mut pipe_screen) -> Option<Self> {
93         if screen.is_null() || !has_required_cbs(screen) {
94             return None;
95         }
96 
97         Some(Self {
98             ldev,
99             // SAFETY: `pipe_screen` is considered a thread-safe type
100             screen: unsafe { ThreadSafeCPtr::new(screen)? },
101         })
102     }
103 
screen(&self) -> &pipe_screen104     fn screen(&self) -> &pipe_screen {
105         // SAFETY: We own the pointer, so it's valid for every caller of this function as we are
106         //         responsible of freeing it.
107         unsafe { self.screen.as_ref() }
108     }
109 
create_context(self: &Arc<Self>) -> Option<PipeContext>110     pub fn create_context(self: &Arc<Self>) -> Option<PipeContext> {
111         PipeContext::new(
112             unsafe {
113                 self.screen().context_create.unwrap()(
114                     self.screen.as_ptr(),
115                     ptr::null_mut(),
116                     PIPE_CONTEXT_COMPUTE_ONLY | PIPE_CONTEXT_NO_LOD_BIAS,
117                 )
118             },
119             self,
120         )
121     }
122 
resource_create(&self, tmpl: &pipe_resource) -> Option<PipeResource>123     fn resource_create(&self, tmpl: &pipe_resource) -> Option<PipeResource> {
124         PipeResource::new(
125             unsafe { self.screen().resource_create.unwrap()(self.screen.as_ptr(), tmpl) },
126             false,
127         )
128     }
129 
resource_create_from_user( &self, tmpl: &pipe_resource, mem: *mut c_void, ) -> Option<PipeResource>130     fn resource_create_from_user(
131         &self,
132         tmpl: &pipe_resource,
133         mem: *mut c_void,
134     ) -> Option<PipeResource> {
135         PipeResource::new(
136             unsafe { self.screen().resource_from_user_memory?(self.screen.as_ptr(), tmpl, mem) },
137             true,
138         )
139     }
140 
resource_create_buffer( &self, size: u32, res_type: ResourceType, pipe_bind: u32, ) -> Option<PipeResource>141     pub fn resource_create_buffer(
142         &self,
143         size: u32,
144         res_type: ResourceType,
145         pipe_bind: u32,
146     ) -> Option<PipeResource> {
147         let mut tmpl = pipe_resource::default();
148 
149         tmpl.set_target(pipe_texture_target::PIPE_BUFFER);
150         tmpl.width0 = size;
151         tmpl.height0 = 1;
152         tmpl.depth0 = 1;
153         tmpl.array_size = 1;
154         tmpl.bind = pipe_bind;
155 
156         res_type.apply(&mut tmpl);
157 
158         self.resource_create(&tmpl)
159     }
160 
resource_create_buffer_from_user( &self, size: u32, mem: *mut c_void, pipe_bind: u32, ) -> Option<PipeResource>161     pub fn resource_create_buffer_from_user(
162         &self,
163         size: u32,
164         mem: *mut c_void,
165         pipe_bind: u32,
166     ) -> Option<PipeResource> {
167         let mut tmpl = pipe_resource::default();
168 
169         tmpl.set_target(pipe_texture_target::PIPE_BUFFER);
170         tmpl.width0 = size;
171         tmpl.height0 = 1;
172         tmpl.depth0 = 1;
173         tmpl.array_size = 1;
174         tmpl.bind = pipe_bind;
175 
176         self.resource_create_from_user(&tmpl, mem)
177     }
178 
resource_create_texture( &self, width: u32, height: u16, depth: u16, array_size: u16, target: pipe_texture_target, format: pipe_format, res_type: ResourceType, support_image: bool, ) -> Option<PipeResource>179     pub fn resource_create_texture(
180         &self,
181         width: u32,
182         height: u16,
183         depth: u16,
184         array_size: u16,
185         target: pipe_texture_target,
186         format: pipe_format,
187         res_type: ResourceType,
188         support_image: bool,
189     ) -> Option<PipeResource> {
190         let mut tmpl = pipe_resource::default();
191 
192         tmpl.set_target(target);
193         tmpl.set_format(format);
194         tmpl.width0 = width;
195         tmpl.height0 = height;
196         tmpl.depth0 = depth;
197         tmpl.array_size = array_size;
198         tmpl.bind = PIPE_BIND_SAMPLER_VIEW;
199 
200         if support_image {
201             tmpl.bind |= PIPE_BIND_SHADER_IMAGE;
202         }
203 
204         res_type.apply(&mut tmpl);
205 
206         self.resource_create(&tmpl)
207     }
208 
resource_create_texture_from_user( &self, width: u32, height: u16, depth: u16, array_size: u16, target: pipe_texture_target, format: pipe_format, mem: *mut c_void, support_image: bool, ) -> Option<PipeResource>209     pub fn resource_create_texture_from_user(
210         &self,
211         width: u32,
212         height: u16,
213         depth: u16,
214         array_size: u16,
215         target: pipe_texture_target,
216         format: pipe_format,
217         mem: *mut c_void,
218         support_image: bool,
219     ) -> Option<PipeResource> {
220         let mut tmpl = pipe_resource::default();
221 
222         tmpl.set_target(target);
223         tmpl.set_format(format);
224         tmpl.width0 = width;
225         tmpl.height0 = height;
226         tmpl.depth0 = depth;
227         tmpl.array_size = array_size;
228         tmpl.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_LINEAR;
229 
230         if support_image {
231             tmpl.bind |= PIPE_BIND_SHADER_IMAGE;
232         }
233 
234         self.resource_create_from_user(&tmpl, mem)
235     }
236 
resource_import_dmabuf( &self, handle: u32, modifier: u64, target: pipe_texture_target, format: pipe_format, stride: u32, width: u32, height: u16, depth: u16, array_size: u16, ) -> Option<PipeResource>237     pub fn resource_import_dmabuf(
238         &self,
239         handle: u32,
240         modifier: u64,
241         target: pipe_texture_target,
242         format: pipe_format,
243         stride: u32,
244         width: u32,
245         height: u16,
246         depth: u16,
247         array_size: u16,
248     ) -> Option<PipeResource> {
249         let mut tmpl = pipe_resource::default();
250         let mut handle = winsys_handle {
251             type_: WINSYS_HANDLE_TYPE_FD,
252             handle: handle,
253             modifier: modifier,
254             format: format as u64,
255             stride: stride,
256             ..Default::default()
257         };
258 
259         tmpl.set_target(target);
260         tmpl.set_format(format);
261         tmpl.width0 = width;
262         tmpl.height0 = height;
263         tmpl.depth0 = depth;
264         tmpl.array_size = array_size;
265 
266         unsafe {
267             PipeResource::new(
268                 self.screen().resource_from_handle.unwrap()(
269                     self.screen.as_ptr(),
270                     &tmpl,
271                     &mut handle,
272                     0,
273                 ),
274                 false,
275             )
276         }
277     }
278 
param(&self, cap: pipe_cap) -> i32279     pub fn param(&self, cap: pipe_cap) -> i32 {
280         unsafe { self.screen().get_param.unwrap()(self.screen.as_ptr(), cap) }
281     }
282 
shader_param(&self, t: pipe_shader_type, cap: pipe_shader_cap) -> i32283     pub fn shader_param(&self, t: pipe_shader_type, cap: pipe_shader_cap) -> i32 {
284         unsafe { self.screen().get_shader_param.unwrap()(self.screen.as_ptr(), t, cap) }
285     }
286 
compute_param_wrapped(&self, cap: pipe_compute_cap, ptr: *mut c_void) -> i32287     fn compute_param_wrapped(&self, cap: pipe_compute_cap, ptr: *mut c_void) -> i32 {
288         unsafe {
289             self.screen().get_compute_param.unwrap()(
290                 self.screen.as_ptr(),
291                 pipe_shader_ir::PIPE_SHADER_IR_NIR,
292                 cap,
293                 ptr,
294             )
295         }
296     }
297 
driver_name(&self) -> String298     pub fn driver_name(&self) -> String {
299         self.ldev.driver_name()
300     }
301 
name(&self) -> &CStr302     pub fn name(&self) -> &CStr {
303         unsafe { CStr::from_ptr(self.screen().get_name.unwrap()(self.screen.as_ptr())) }
304     }
305 
device_node_mask(&self) -> Option<u32>306     pub fn device_node_mask(&self) -> Option<u32> {
307         unsafe { Some(self.screen().get_device_node_mask?(self.screen.as_ptr())) }
308     }
309 
device_uuid(&self) -> Option<[c_uchar; UUID_SIZE]>310     pub fn device_uuid(&self) -> Option<[c_uchar; UUID_SIZE]> {
311         let mut uuid = [0; UUID_SIZE];
312         let ptr = uuid.as_mut_ptr();
313         unsafe {
314             self.screen().get_device_uuid?(self.screen.as_ptr(), ptr.cast());
315         }
316 
317         Some(uuid)
318     }
319 
device_luid(&self) -> Option<[c_uchar; LUID_SIZE]>320     pub fn device_luid(&self) -> Option<[c_uchar; LUID_SIZE]> {
321         let mut luid = [0; LUID_SIZE];
322         let ptr = luid.as_mut_ptr();
323         unsafe { self.screen().get_device_luid?(self.screen.as_ptr(), ptr.cast()) }
324 
325         Some(luid)
326     }
327 
device_vendor(&self) -> &CStr328     pub fn device_vendor(&self) -> &CStr {
329         unsafe {
330             CStr::from_ptr(self.screen().get_device_vendor.unwrap()(
331                 self.screen.as_ptr(),
332             ))
333         }
334     }
335 
device_type(&self) -> pipe_loader_device_type336     pub fn device_type(&self) -> pipe_loader_device_type {
337         self.ldev.device_type()
338     }
339 
driver_uuid(&self) -> Option<[c_schar; UUID_SIZE]>340     pub fn driver_uuid(&self) -> Option<[c_schar; UUID_SIZE]> {
341         let mut uuid = [0; UUID_SIZE];
342         let ptr = uuid.as_mut_ptr();
343         unsafe {
344             self.screen().get_driver_uuid?(self.screen.as_ptr(), ptr.cast());
345         }
346 
347         Some(uuid)
348     }
349 
cl_cts_version(&self) -> &CStr350     pub fn cl_cts_version(&self) -> &CStr {
351         unsafe {
352             let ptr = self
353                 .screen()
354                 .get_cl_cts_version
355                 .map_or(ptr::null(), |get_cl_cts_version| {
356                     get_cl_cts_version(self.screen.as_ptr())
357                 });
358             if ptr.is_null() {
359                 // this string is good enough to pass the CTS
360                 CStr::from_bytes_with_nul(b"v0000-01-01-00\0").unwrap()
361             } else {
362                 CStr::from_ptr(ptr)
363             }
364         }
365     }
366 
is_format_supported( &self, format: pipe_format, target: pipe_texture_target, bindings: u32, ) -> bool367     pub fn is_format_supported(
368         &self,
369         format: pipe_format,
370         target: pipe_texture_target,
371         bindings: u32,
372     ) -> bool {
373         unsafe {
374             self.screen().is_format_supported.unwrap()(
375                 self.screen.as_ptr(),
376                 format,
377                 target,
378                 0,
379                 0,
380                 bindings,
381             )
382         }
383     }
384 
get_timestamp(&self) -> u64385     pub fn get_timestamp(&self) -> u64 {
386         unsafe {
387             self.screen()
388                 .get_timestamp
389                 .unwrap_or(u_default_get_timestamp)(self.screen.as_ptr())
390         }
391     }
392 
is_res_handle_supported(&self) -> bool393     pub fn is_res_handle_supported(&self) -> bool {
394         self.screen().resource_from_handle.is_some() && self.screen().resource_get_handle.is_some()
395     }
396 
nir_shader_compiler_options( &self, shader: pipe_shader_type, ) -> *const nir_shader_compiler_options397     pub fn nir_shader_compiler_options(
398         &self,
399         shader: pipe_shader_type,
400     ) -> *const nir_shader_compiler_options {
401         unsafe {
402             self.screen().get_compiler_options.unwrap()(
403                 self.screen.as_ptr(),
404                 pipe_shader_ir::PIPE_SHADER_IR_NIR,
405                 shader,
406             )
407             .cast()
408         }
409     }
410 
shader_cache(&self) -> Option<DiskCacheBorrowed>411     pub fn shader_cache(&self) -> Option<DiskCacheBorrowed> {
412         let ptr = unsafe { self.screen().get_disk_shader_cache?(self.screen.as_ptr()) };
413 
414         DiskCacheBorrowed::from_ptr(ptr)
415     }
416 
417     /// returns true if finalize_nir was called
finalize_nir(&self, nir: &NirShader) -> bool418     pub fn finalize_nir(&self, nir: &NirShader) -> bool {
419         if let Some(func) = self.screen().finalize_nir {
420             unsafe {
421                 func(self.screen.as_ptr(), nir.get_nir().cast());
422             }
423             true
424         } else {
425             false
426         }
427     }
428 
unref_fence(&self, mut fence: *mut pipe_fence_handle)429     pub(super) fn unref_fence(&self, mut fence: *mut pipe_fence_handle) {
430         unsafe {
431             self.screen().fence_reference.unwrap()(
432                 self.screen.as_ptr(),
433                 &mut fence,
434                 ptr::null_mut(),
435             );
436         }
437     }
438 
fence_finish(&self, fence: *mut pipe_fence_handle)439     pub(super) fn fence_finish(&self, fence: *mut pipe_fence_handle) {
440         unsafe {
441             self.screen().fence_finish.unwrap()(
442                 self.screen.as_ptr(),
443                 ptr::null_mut(),
444                 fence,
445                 OS_TIMEOUT_INFINITE as u64,
446             );
447         }
448     }
449 
query_memory_info(&self) -> Option<pipe_memory_info>450     pub fn query_memory_info(&self) -> Option<pipe_memory_info> {
451         let mut info = pipe_memory_info::default();
452         unsafe {
453             self.screen().query_memory_info?(self.screen.as_ptr(), &mut info);
454         }
455         Some(info)
456     }
457 }
458 
459 impl Drop for PipeScreen {
drop(&mut self)460     fn drop(&mut self) {
461         unsafe { self.screen().destroy.unwrap()(self.screen.as_ptr()) }
462     }
463 }
464 
has_required_cbs(screen: *mut pipe_screen) -> bool465 fn has_required_cbs(screen: *mut pipe_screen) -> bool {
466     let screen = unsafe { *screen };
467     // Use '&' to evaluate all features and to not stop
468     // on first missing one to list all missing features.
469     has_required_feature!(screen, context_create)
470         & has_required_feature!(screen, destroy)
471         & has_required_feature!(screen, fence_finish)
472         & has_required_feature!(screen, fence_reference)
473         & has_required_feature!(screen, get_compiler_options)
474         & has_required_feature!(screen, get_compute_param)
475         & has_required_feature!(screen, get_name)
476         & has_required_feature!(screen, get_param)
477         & has_required_feature!(screen, get_shader_param)
478         & has_required_feature!(screen, is_format_supported)
479         & has_required_feature!(screen, resource_create)
480 }
481