1use crate::Result;
10use bytemuck::Pod;
11use sycl_rs_sys::{queue::ffi, types::ffi::EventPtr};
12
13use crate::{
14 context::Context,
15 device::Device,
16 event::Event,
17 kernel::{Kernel, KernelArgumentList},
18 range::{NdRange, ValidDimension},
19 usm::{UsmAlloc, UsmAllocator},
20 usmbox::{
21 DeviceUsmBox, EnqueuedDeviceUsmBox, EnqueuedHostUsmBox, EnqueuedSharedUsmBox,
22 EnqueuedUsmBox, HostUsmBox, SharedUsmBox, UsmBox,
23 },
24};
25
26pub struct Queue(pub(crate) cxx::UniquePtr<ffi::Queue>);
30
31#[allow(clippy::new_without_default)]
33impl Queue {
34 pub fn new() -> Self {
36 Self(ffi::new_queue())
37 }
38
39 pub fn new_immediate() -> Self {
41 Self(ffi::new_queue_immediate())
42 }
43
44 pub fn get_context(&self) -> Context {
46 ffi::get_context(&self.0).into()
47 }
48
49 pub fn get_device(&self) -> Device {
51 ffi::get_device(&self.0).into()
52 }
53
54 pub fn alloc_host<T: Pod>(&mut self, len: usize) -> Result<EnqueuedHostUsmBox<T>> {
56 unsafe {
57 let mut array = self.alloc_uninit_host(len);
58 self.memset(&mut array, 0)
59 .map(|event| EnqueuedUsmBox::new(array, event))
60 }
61 }
62
63 pub fn alloc_shared<T: Pod>(&mut self, len: usize) -> Result<EnqueuedSharedUsmBox<T>> {
65 unsafe {
66 let mut array = self.alloc_uninit_shared(len);
67 self.memset(&mut array, 0)
68 .map(|event| EnqueuedUsmBox::new(array, event))
69 }
70 }
71
72 pub fn alloc_device<T: Pod>(&mut self, len: usize) -> Result<EnqueuedDeviceUsmBox<T>> {
74 unsafe {
75 let mut array = self.alloc_uninit_device(len);
76 self.memset(&mut array, 0)
77 .map(|event| EnqueuedUsmBox::new(array, event))
78 }
79 }
80
81 pub unsafe fn alloc_uninit_host<T>(&self, len: usize) -> HostUsmBox<T> {
87 let allocator = UsmAllocator::from(self);
88 unsafe { UsmBox::new(allocator, len) }
89 }
90
91 pub unsafe fn alloc_uninit_shared<T>(&self, len: usize) -> SharedUsmBox<T> {
97 let allocator = UsmAllocator::from(self);
98 unsafe { UsmBox::new(allocator, len) }
99 }
100
101 pub unsafe fn alloc_uninit_device<T>(&self, len: usize) -> DeviceUsmBox<T> {
107 let allocator = UsmAllocator::from(self);
108 unsafe { UsmBox::new(allocator, len) }
109 }
110
111 pub unsafe fn memset<T, A: UsmAlloc>(
117 &mut self,
118 array: &mut UsmBox<T, A>,
119 value: i32,
120 ) -> Result<Event> {
121 unsafe { self.memset_with_deps(array, value, &[]) }
122 }
123
124 pub unsafe fn memset_with_deps<T, A: UsmAlloc>(
130 &mut self,
131 array: &mut UsmBox<T, A>,
132 value: i32,
133 dep_events: &[&Event],
134 ) -> Result<Event> {
135 let ptr = array.get_byte_ptr();
136 let num_bytes = array.get_byte_size();
137 let dep_events = dep_events
138 .iter()
139 .map(|e| EventPtr {
140 ptr: (*e).clone().0,
141 })
142 .collect::<Vec<_>>();
143 unsafe { ffi::memset(&mut self.0, ptr, value, num_bytes, dep_events) }.map(Into::into)
144 }
145
146 pub fn barrier(&mut self) -> Result<Event> {
148 self.barrier_with_deps(&[])
149 }
150
151 pub fn barrier_with_deps(&mut self, dep_events: &[&Event]) -> Result<Event> {
153 let dep_events = dep_events
154 .iter()
155 .map(|e| EventPtr {
156 ptr: (*e).clone().0,
157 })
158 .collect::<Vec<_>>();
159 ffi::barrier(&mut self.0, dep_events).map(Into::into)
160 }
161
162 pub fn wait(&mut self) -> Result<()> {
167 ffi::wait(&mut self.0)
168 }
169
170 pub unsafe fn launch<const ARGC: usize, const DIMENSIONS: usize>(
178 &mut self,
179 nd_range: NdRange<DIMENSIONS>,
180 kernel: &Kernel,
181 args: impl KernelArgumentList<ARGC>,
182 ) -> Result<Event>
183 where
184 NdRange<DIMENSIONS>: ValidDimension,
185 {
186 unsafe { nd_range.launch(self, kernel, args) }
187 }
188
189 pub fn copy<T, A1, A2>(&mut self, src: &UsmBox<T, A1>, dst: &mut UsmBox<T, A2>) -> Result<Event>
193 where
194 T: Pod,
195 A1: UsmAlloc,
196 A2: UsmAlloc,
197 {
198 self.copy_with_deps(src, dst, &[])
199 }
200
201 pub fn copy_with_deps<T, A1, A2>(
206 &mut self,
207 src: &UsmBox<T, A1>,
208 dst: &mut UsmBox<T, A2>,
209 dep_events: &[&Event],
210 ) -> Result<Event>
211 where
212 T: Pod,
213 A1: UsmAlloc,
214 A2: UsmAlloc,
215 {
216 assert_eq!(
217 src.get_len(),
218 dst.get_len(),
219 "source and destination array lengths differ"
220 );
221
222 let dep_events = dep_events
224 .iter()
225 .map(|e| EventPtr {
226 ptr: (*e).clone().0,
227 })
228 .collect::<Vec<_>>();
229
230 let num_bytes = src.get_len() * size_of::<T>();
231 unsafe {
232 ffi::memcpy(
233 &mut self.0,
234 dst.get_byte_ptr(),
235 src.get_byte_ptr(),
236 num_bytes,
237 dep_events,
238 )
239 }
240 .map(Into::into)
241 }
242}
243
244impl From<&Device> for Queue {
245 fn from(value: &Device) -> Self {
246 Self(ffi::new_queue_from_device(&value.0))
247 }
248}
249
250impl From<(&Context, &Device)> for Queue {
251 fn from(value: (&Context, &Device)) -> Self {
252 Self(ffi::new_queue_from_context_and_device(
253 &value.0.0, &value.1.0,
254 ))
255 }
256}
257
258impl From<cxx::UniquePtr<ffi::Queue>> for Queue {
259 fn from(value: cxx::UniquePtr<ffi::Queue>) -> Self {
260 Self(value)
261 }
262}
263
264impl Clone for Queue {
265 fn clone(&self) -> Self {
266 ffi::clone(&self.0).into()
267 }
268}