xref: /aosp_15_r20/external/mesa3d/src/gallium/frontends/rusticl/core/context.rs (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 use crate::api::icd::*;
2 use crate::api::types::DeleteContextCB;
3 use crate::core::device::*;
4 use crate::core::format::*;
5 use crate::core::gl::*;
6 use crate::core::memory::*;
7 use crate::core::util::*;
8 use crate::impl_cl_type_trait;
9 
10 use mesa_rust::pipe::resource::*;
11 use mesa_rust::pipe::screen::ResourceType;
12 use mesa_rust_gen::*;
13 use mesa_rust_util::properties::Properties;
14 use mesa_rust_util::ptr::TrackedPointers;
15 use rusticl_opencl_gen::*;
16 
17 use std::alloc::Layout;
18 use std::collections::HashMap;
19 use std::convert::TryInto;
20 use std::mem;
21 use std::os::raw::c_void;
22 use std::sync::Arc;
23 use std::sync::Mutex;
24 
25 pub struct Context {
26     pub base: CLObjectBase<CL_INVALID_CONTEXT>,
27     pub devs: Vec<&'static Device>,
28     pub properties: Properties<cl_context_properties>,
29     pub dtors: Mutex<Vec<DeleteContextCB>>,
30     svm_ptrs: Mutex<TrackedPointers<usize, Layout>>,
31     pub gl_ctx_manager: Option<GLCtxManager>,
32 }
33 
34 impl_cl_type_trait!(cl_context, Context, CL_INVALID_CONTEXT);
35 
36 impl Context {
new( devs: Vec<&'static Device>, properties: Properties<cl_context_properties>, gl_ctx_manager: Option<GLCtxManager>, ) -> Arc<Context>37     pub fn new(
38         devs: Vec<&'static Device>,
39         properties: Properties<cl_context_properties>,
40         gl_ctx_manager: Option<GLCtxManager>,
41     ) -> Arc<Context> {
42         Arc::new(Self {
43             base: CLObjectBase::new(RusticlTypes::Context),
44             devs: devs,
45             properties: properties,
46             dtors: Mutex::new(Vec::new()),
47             svm_ptrs: Mutex::new(TrackedPointers::new()),
48             gl_ctx_manager: gl_ctx_manager,
49         })
50     }
51 
create_buffer( &self, size: usize, user_ptr: *mut c_void, copy: bool, res_type: ResourceType, ) -> CLResult<HashMap<&'static Device, Arc<PipeResource>>>52     pub fn create_buffer(
53         &self,
54         size: usize,
55         user_ptr: *mut c_void,
56         copy: bool,
57         res_type: ResourceType,
58     ) -> CLResult<HashMap<&'static Device, Arc<PipeResource>>> {
59         let adj_size: u32 = size.try_into().map_err(|_| CL_OUT_OF_HOST_MEMORY)?;
60         let mut res = HashMap::new();
61         for &dev in &self.devs {
62             let mut resource = None;
63 
64             if !user_ptr.is_null() && !copy {
65                 resource = dev.screen().resource_create_buffer_from_user(
66                     adj_size,
67                     user_ptr,
68                     PIPE_BIND_GLOBAL,
69                 )
70             }
71 
72             if resource.is_none() {
73                 resource = dev
74                     .screen()
75                     .resource_create_buffer(adj_size, res_type, PIPE_BIND_GLOBAL)
76             }
77 
78             let resource = resource.ok_or(CL_OUT_OF_RESOURCES);
79             res.insert(dev, Arc::new(resource?));
80         }
81 
82         if !user_ptr.is_null() {
83             res.iter()
84                 .filter(|(_, r)| copy || !r.is_user())
85                 .map(|(d, r)| {
86                     d.helper_ctx()
87                         .exec(|ctx| ctx.buffer_subdata(r, 0, user_ptr, size.try_into().unwrap()))
88                 })
89                 .for_each(|f| f.wait());
90         }
91 
92         Ok(res)
93     }
94 
create_texture( &self, desc: &cl_image_desc, format: &cl_image_format, user_ptr: *mut c_void, copy: bool, res_type: ResourceType, ) -> CLResult<HashMap<&'static Device, Arc<PipeResource>>>95     pub fn create_texture(
96         &self,
97         desc: &cl_image_desc,
98         format: &cl_image_format,
99         user_ptr: *mut c_void,
100         copy: bool,
101         res_type: ResourceType,
102     ) -> CLResult<HashMap<&'static Device, Arc<PipeResource>>> {
103         let pipe_format = format.to_pipe_format().unwrap();
104 
105         let width = desc
106             .image_width
107             .try_into()
108             .map_err(|_| CL_OUT_OF_HOST_MEMORY)?;
109         let height = desc
110             .image_height
111             .try_into()
112             .map_err(|_| CL_OUT_OF_HOST_MEMORY)?;
113         let depth = desc
114             .image_depth
115             .try_into()
116             .map_err(|_| CL_OUT_OF_HOST_MEMORY)?;
117         let array_size = desc
118             .image_array_size
119             .try_into()
120             .map_err(|_| CL_OUT_OF_HOST_MEMORY)?;
121         let target = cl_mem_type_to_texture_target(desc.image_type);
122 
123         let mut res = HashMap::new();
124         for &dev in &self.devs {
125             let mut resource = None;
126             let enable_bind_as_image =
127                 (dev.formats[format][&desc.image_type] as u32 & CL_MEM_WRITE_ONLY) != 0;
128 
129             // we can't specify custom pitches/slices, so this won't work for non 1D images
130             if !user_ptr.is_null() && !copy && desc.image_type == CL_MEM_OBJECT_IMAGE1D {
131                 resource = dev.screen().resource_create_texture_from_user(
132                     width,
133                     height,
134                     depth,
135                     array_size,
136                     target,
137                     pipe_format,
138                     user_ptr,
139                     enable_bind_as_image,
140                 )
141             }
142 
143             if resource.is_none() {
144                 resource = dev.screen().resource_create_texture(
145                     width,
146                     height,
147                     depth,
148                     array_size,
149                     target,
150                     pipe_format,
151                     res_type,
152                     enable_bind_as_image,
153                 )
154             }
155 
156             let resource = resource.ok_or(CL_OUT_OF_RESOURCES);
157             res.insert(dev, Arc::new(resource?));
158         }
159 
160         if !user_ptr.is_null() {
161             let bx = desc.bx()?;
162             let stride = desc.row_pitch()?;
163             let layer_stride = desc.slice_pitch();
164 
165             res.iter()
166                 .filter(|(_, r)| copy || !r.is_user())
167                 .map(|(d, r)| {
168                     d.helper_ctx()
169                         .exec(|ctx| ctx.texture_subdata(r, &bx, user_ptr, stride, layer_stride))
170                 })
171                 .for_each(|f| f.wait());
172         }
173 
174         Ok(res)
175     }
176 
177     /// Returns the max allocation size supported by all devices
max_mem_alloc(&self) -> u64178     pub fn max_mem_alloc(&self) -> u64 {
179         self.devs
180             .iter()
181             .map(|dev| dev.max_mem_alloc())
182             .min()
183             .unwrap()
184     }
185 
has_svm_devs(&self) -> bool186     pub fn has_svm_devs(&self) -> bool {
187         self.devs.iter().any(|dev| dev.svm_supported())
188     }
189 
add_svm_ptr(&self, ptr: usize, layout: Layout)190     pub fn add_svm_ptr(&self, ptr: usize, layout: Layout) {
191         self.svm_ptrs.lock().unwrap().insert(ptr, layout);
192     }
193 
find_svm_alloc(&self, ptr: usize) -> Option<(*const c_void, usize)>194     pub fn find_svm_alloc(&self, ptr: usize) -> Option<(*const c_void, usize)> {
195         self.svm_ptrs
196             .lock()
197             .unwrap()
198             .find_alloc(ptr)
199             .map(|(ptr, layout)| (ptr as *const c_void, layout.size()))
200     }
201 
remove_svm_ptr(&self, ptr: usize) -> Option<Layout>202     pub fn remove_svm_ptr(&self, ptr: usize) -> Option<Layout> {
203         self.svm_ptrs.lock().unwrap().remove(ptr)
204     }
205 
import_gl_buffer( &self, handle: u32, modifier: u64, image_type: cl_mem_object_type, gl_target: cl_GLenum, format: pipe_format, gl_props: GLMemProps, ) -> CLResult<HashMap<&'static Device, Arc<PipeResource>>>206     pub fn import_gl_buffer(
207         &self,
208         handle: u32,
209         modifier: u64,
210         image_type: cl_mem_object_type,
211         gl_target: cl_GLenum,
212         format: pipe_format,
213         gl_props: GLMemProps,
214     ) -> CLResult<HashMap<&'static Device, Arc<PipeResource>>> {
215         let mut res = HashMap::new();
216         let target = cl_mem_type_to_texture_target_gl(image_type, gl_target);
217 
218         for dev in &self.devs {
219             let resource = dev
220                 .screen()
221                 .resource_import_dmabuf(
222                     handle,
223                     modifier,
224                     target,
225                     format,
226                     gl_props.stride,
227                     gl_props.width,
228                     gl_props.height,
229                     gl_props.depth,
230                     gl_props.array_size,
231                 )
232                 .ok_or(CL_OUT_OF_RESOURCES)?;
233 
234             res.insert(*dev, Arc::new(resource));
235         }
236 
237         Ok(res)
238     }
239 }
240 
241 impl Drop for Context {
drop(&mut self)242     fn drop(&mut self) {
243         let cbs = mem::take(self.dtors.get_mut().unwrap());
244         for cb in cbs.into_iter().rev() {
245             cb.call(self);
246         }
247     }
248 }
249