• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::api::event::create_and_queue;
2 use crate::api::icd::*;
3 use crate::api::util::*;
4 use crate::core::context::*;
5 use crate::core::device::*;
6 use crate::core::event::*;
7 use crate::core::queue::*;
8 
9 use mesa_rust_util::properties::*;
10 use rusticl_opencl_gen::*;
11 use rusticl_proc_macros::cl_entrypoint;
12 use rusticl_proc_macros::cl_info_entrypoint;
13 
14 use std::mem::MaybeUninit;
15 use std::ptr;
16 use std::sync::Arc;
17 
18 #[cl_info_entrypoint(cl_get_command_queue_info)]
19 impl CLInfo<cl_command_queue_info> for cl_command_queue {
query(&self, q: cl_command_queue_info, _: &[u8]) -> CLResult<Vec<MaybeUninit<u8>>>20     fn query(&self, q: cl_command_queue_info, _: &[u8]) -> CLResult<Vec<MaybeUninit<u8>>> {
21         let queue = Queue::ref_from_raw(*self)?;
22         Ok(match q {
23             CL_QUEUE_CONTEXT => {
24                 // Note we use as_ptr here which doesn't increase the reference count.
25                 let ptr = Arc::as_ptr(&queue.context);
26                 cl_prop::<cl_context>(cl_context::from_ptr(ptr))
27             }
28             CL_QUEUE_DEVICE => cl_prop::<cl_device_id>(cl_device_id::from_ptr(queue.device)),
29             CL_QUEUE_DEVICE_DEFAULT => cl_prop::<cl_command_queue>(ptr::null_mut()),
30             CL_QUEUE_PROPERTIES => cl_prop::<cl_command_queue_properties>(queue.props),
31             CL_QUEUE_PROPERTIES_ARRAY => {
32                 cl_prop::<&Option<Properties<cl_queue_properties>>>(&queue.props_v2)
33             }
34             CL_QUEUE_REFERENCE_COUNT => cl_prop::<cl_uint>(Queue::refcnt(*self)?),
35             // clGetCommandQueueInfo, passing CL_QUEUE_SIZE Returns CL_INVALID_COMMAND_QUEUE since
36             // command_queue cannot be a valid device command-queue.
37             CL_QUEUE_SIZE => return Err(CL_INVALID_COMMAND_QUEUE),
38             // CL_INVALID_VALUE if param_name is not one of the supported values
39             _ => return Err(CL_INVALID_VALUE),
40         })
41     }
42 }
43 
valid_command_queue_properties(properties: cl_command_queue_properties) -> bool44 fn valid_command_queue_properties(properties: cl_command_queue_properties) -> bool {
45     let valid_flags = cl_bitfield::from(
46         CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE
47             | CL_QUEUE_PROFILING_ENABLE
48             | CL_QUEUE_ON_DEVICE
49             | CL_QUEUE_ON_DEVICE_DEFAULT,
50     );
51     properties & !valid_flags == 0
52 }
53 
supported_command_queue_properties( dev: &Device, properties: cl_command_queue_properties, ) -> bool54 fn supported_command_queue_properties(
55     dev: &Device,
56     properties: cl_command_queue_properties,
57 ) -> bool {
58     let profiling = cl_bitfield::from(CL_QUEUE_PROFILING_ENABLE);
59     let valid_flags = profiling;
60     if properties & !valid_flags != 0 {
61         return false;
62     }
63 
64     if properties & profiling != 0 && !dev.has_timestamp {
65         return false;
66     }
67 
68     true
69 }
70 
create_command_queue_impl( context: cl_context, device: cl_device_id, properties: cl_command_queue_properties, properties_v2: Option<Properties<cl_queue_properties>>, ) -> CLResult<cl_command_queue>71 pub fn create_command_queue_impl(
72     context: cl_context,
73     device: cl_device_id,
74     properties: cl_command_queue_properties,
75     properties_v2: Option<Properties<cl_queue_properties>>,
76 ) -> CLResult<cl_command_queue> {
77     let c = Context::arc_from_raw(context)?;
78     let d = Device::ref_from_raw(device)?
79         .to_static()
80         .ok_or(CL_INVALID_DEVICE)?;
81 
82     // CL_INVALID_DEVICE if device [...] is not associated with context.
83     if !c.devs.contains(&d) {
84         return Err(CL_INVALID_DEVICE);
85     }
86 
87     // CL_INVALID_VALUE if values specified in properties are not valid.
88     if !valid_command_queue_properties(properties) {
89         return Err(CL_INVALID_VALUE);
90     }
91 
92     // CL_INVALID_QUEUE_PROPERTIES if values specified in properties are valid but are not supported by the device.
93     if !supported_command_queue_properties(d, properties) {
94         return Err(CL_INVALID_QUEUE_PROPERTIES);
95     }
96 
97     Ok(Queue::new(c, d, properties, properties_v2)?.into_cl())
98 }
99 
100 #[cl_entrypoint]
create_command_queue( context: cl_context, device: cl_device_id, properties: cl_command_queue_properties, ) -> CLResult<cl_command_queue>101 fn create_command_queue(
102     context: cl_context,
103     device: cl_device_id,
104     properties: cl_command_queue_properties,
105 ) -> CLResult<cl_command_queue> {
106     create_command_queue_impl(context, device, properties, None)
107 }
108 
109 #[cl_entrypoint]
create_command_queue_with_properties( context: cl_context, device: cl_device_id, properties: *const cl_queue_properties, ) -> CLResult<cl_command_queue>110 fn create_command_queue_with_properties(
111     context: cl_context,
112     device: cl_device_id,
113     properties: *const cl_queue_properties,
114 ) -> CLResult<cl_command_queue> {
115     let mut queue_properties = cl_command_queue_properties::default();
116     let properties = if properties.is_null() {
117         None
118     } else {
119         let properties = Properties::from_ptr(properties).ok_or(CL_INVALID_PROPERTY)?;
120 
121         for (k, v) in &properties.props {
122             match *k as cl_uint {
123                 CL_QUEUE_PROPERTIES => queue_properties = *v,
124                 // CL_INVALID_QUEUE_PROPERTIES if values specified in properties are valid but are not
125                 // supported by the device.
126                 CL_QUEUE_SIZE => return Err(CL_INVALID_QUEUE_PROPERTIES),
127                 _ => return Err(CL_INVALID_PROPERTY),
128             }
129         }
130 
131         Some(properties)
132     };
133 
134     create_command_queue_impl(context, device, queue_properties, properties)
135 }
136 
137 #[cl_entrypoint]
enqueue_marker(command_queue: cl_command_queue, event: *mut cl_event) -> CLResult<()>138 fn enqueue_marker(command_queue: cl_command_queue, event: *mut cl_event) -> CLResult<()> {
139     let q = Queue::arc_from_raw(command_queue)?;
140 
141     // TODO marker makes sure previous commands did complete
142     create_and_queue(
143         q,
144         CL_COMMAND_MARKER,
145         Vec::new(),
146         event,
147         false,
148         Box::new(|_, _| Ok(())),
149     )
150 }
151 
152 #[cl_entrypoint]
enqueue_marker_with_wait_list( command_queue: cl_command_queue, num_events_in_wait_list: cl_uint, event_wait_list: *const cl_event, event: *mut cl_event, ) -> CLResult<()>153 fn enqueue_marker_with_wait_list(
154     command_queue: cl_command_queue,
155     num_events_in_wait_list: cl_uint,
156     event_wait_list: *const cl_event,
157     event: *mut cl_event,
158 ) -> CLResult<()> {
159     let q = Queue::arc_from_raw(command_queue)?;
160     let evs = event_list_from_cl(&q, num_events_in_wait_list, event_wait_list)?;
161 
162     // TODO marker makes sure previous commands did complete
163     create_and_queue(
164         q,
165         CL_COMMAND_MARKER,
166         evs,
167         event,
168         false,
169         Box::new(|_, _| Ok(())),
170     )
171 }
172 
173 #[cl_entrypoint]
enqueue_barrier(command_queue: cl_command_queue) -> CLResult<()>174 fn enqueue_barrier(command_queue: cl_command_queue) -> CLResult<()> {
175     let q = Queue::arc_from_raw(command_queue)?;
176 
177     // TODO barriers make sure previous commands did complete and other commands didn't start
178     let e = Event::new(&q, CL_COMMAND_BARRIER, Vec::new(), Box::new(|_, _| Ok(())));
179     q.queue(e);
180     Ok(())
181 }
182 
183 #[cl_entrypoint]
enqueue_barrier_with_wait_list( command_queue: cl_command_queue, num_events_in_wait_list: cl_uint, event_wait_list: *const cl_event, event: *mut cl_event, ) -> CLResult<()>184 fn enqueue_barrier_with_wait_list(
185     command_queue: cl_command_queue,
186     num_events_in_wait_list: cl_uint,
187     event_wait_list: *const cl_event,
188     event: *mut cl_event,
189 ) -> CLResult<()> {
190     let q = Queue::arc_from_raw(command_queue)?;
191     let evs = event_list_from_cl(&q, num_events_in_wait_list, event_wait_list)?;
192 
193     // TODO barriers make sure previous commands did complete and other commands didn't start
194     create_and_queue(
195         q,
196         CL_COMMAND_BARRIER,
197         evs,
198         event,
199         false,
200         Box::new(|_, _| Ok(())),
201     )
202 }
203 
204 #[cl_entrypoint]
flush(command_queue: cl_command_queue) -> CLResult<()>205 fn flush(command_queue: cl_command_queue) -> CLResult<()> {
206     // CL_INVALID_COMMAND_QUEUE if command_queue is not a valid host command-queue.
207     Queue::ref_from_raw(command_queue)?.flush(false)
208 }
209 
210 #[cl_entrypoint]
finish(command_queue: cl_command_queue) -> CLResult<()>211 fn finish(command_queue: cl_command_queue) -> CLResult<()> {
212     // CL_INVALID_COMMAND_QUEUE if command_queue is not a valid host command-queue.
213     Queue::ref_from_raw(command_queue)?.flush(true)
214 }
215 
216 #[cl_entrypoint]
retain_command_queue(command_queue: cl_command_queue) -> CLResult<()>217 fn retain_command_queue(command_queue: cl_command_queue) -> CLResult<()> {
218     Queue::retain(command_queue)
219 }
220 
221 #[cl_entrypoint]
release_command_queue(command_queue: cl_command_queue) -> CLResult<()>222 fn release_command_queue(command_queue: cl_command_queue) -> CLResult<()> {
223     // clReleaseCommandQueue performs an implicit flush to issue any previously queued OpenCL
224     // commands in command_queue.
225     flush(command_queue)?;
226     Queue::release(command_queue)
227 }
228