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
31impl Queue {
32 pub fn new() -> Self {
34 Self(ffi::new_queue())
35 }
36
37 pub fn new_immediate() -> Self {
39 Self(ffi::new_queue_immediate())
40 }
41
42 pub fn get_context(&self) -> Context {
44 ffi::get_context(&self.0).into()
45 }
46
47 pub fn get_device(&self) -> Device {
49 ffi::get_device(&self.0).into()
50 }
51
52 pub fn alloc_host<T: Pod>(&mut self, len: usize) -> Result<EnqueuedHostUsmBox<T>> {
54 unsafe {
55 let mut array = self.alloc_uninit_host(len);
56 self.memset(&mut array, 0)
57 .map(|event| EnqueuedUsmBox::new(array, event))
58 }
59 }
60
61 pub fn alloc_shared<T: Pod>(&mut self, len: usize) -> Result<EnqueuedSharedUsmBox<T>> {
63 unsafe {
64 let mut array = self.alloc_uninit_shared(len);
65 self.memset(&mut array, 0)
66 .map(|event| EnqueuedUsmBox::new(array, event))
67 }
68 }
69
70 pub fn alloc_device<T: Pod>(&mut self, len: usize) -> Result<EnqueuedDeviceUsmBox<T>> {
72 unsafe {
73 let mut array = self.alloc_uninit_device(len);
74 self.memset(&mut array, 0)
75 .map(|event| EnqueuedUsmBox::new(array, event))
76 }
77 }
78
79 pub unsafe fn alloc_uninit_host<T>(&self, len: usize) -> HostUsmBox<T> {
82 let allocator = UsmAllocator::from(self);
83 unsafe { UsmBox::new(allocator, len) }
84 }
85
86 pub unsafe fn alloc_uninit_shared<T>(&self, len: usize) -> SharedUsmBox<T> {
89 let allocator = UsmAllocator::from(self);
90 unsafe { UsmBox::new(allocator, len) }
91 }
92
93 pub unsafe fn alloc_uninit_device<T>(&self, len: usize) -> DeviceUsmBox<T> {
96 let allocator = UsmAllocator::from(self);
97 unsafe { UsmBox::new(allocator, len) }
98 }
99
100 pub unsafe fn memset<T, A: UsmAlloc>(
103 &mut self,
104 array: &mut UsmBox<T, A>,
105 value: i32,
106 ) -> Result<Event> {
107 unsafe { self.memset_with_deps(array, value, &[]) }
108 }
109
110 pub unsafe fn memset_with_deps<T, A: UsmAlloc>(
113 &mut self,
114 array: &mut UsmBox<T, A>,
115 value: i32,
116 dep_events: &[&Event],
117 ) -> Result<Event> {
118 let ptr = array.get_byte_ptr();
119 let num_bytes = array.get_byte_size();
120 let dep_events = dep_events
121 .iter()
122 .map(|e| EventPtr {
123 ptr: (*e).clone().0,
124 })
125 .collect::<Vec<_>>();
126 unsafe { ffi::memset(&mut self.0, ptr, value, num_bytes, dep_events) }.map(Into::into)
127 }
128
129 pub fn barrier(&mut self) -> Result<Event> {
131 self.barrier_with_deps(&[]).map(Into::into)
132 }
133
134 pub fn barrier_with_deps(&mut self, dep_events: &[&Event]) -> Result<Event> {
136 let dep_events = dep_events
137 .iter()
138 .map(|e| EventPtr {
139 ptr: (*e).clone().0,
140 })
141 .collect::<Vec<_>>();
142 ffi::barrier(&mut self.0, dep_events).map(Into::into)
143 }
144
145 pub fn wait(&mut self) -> Result<()> {
150 ffi::wait(&mut self.0)
151 }
152
153 pub unsafe fn launch<const ARGC: usize, const DIMENSIONS: usize>(
159 &mut self,
160 nd_range: NdRange<DIMENSIONS>,
161 kernel: &Kernel,
162 args: impl KernelArgumentList<ARGC>,
163 ) -> Result<Event>
164 where
165 NdRange<DIMENSIONS>: ValidDimension,
166 {
167 unsafe { nd_range.launch(self, kernel, args) }
168 }
169
170 pub fn copy<T, A1, A2>(&mut self, src: &UsmBox<T, A1>, dst: &mut UsmBox<T, A2>) -> Result<Event>
174 where
175 T: Pod,
176 A1: UsmAlloc,
177 A2: UsmAlloc,
178 {
179 self.copy_with_deps(src, dst, &[])
180 }
181
182 pub fn copy_with_deps<T, A1, A2>(
187 &mut self,
188 src: &UsmBox<T, A1>,
189 dst: &mut UsmBox<T, A2>,
190 dep_events: &[&Event],
191 ) -> Result<Event>
192 where
193 T: Pod,
194 A1: UsmAlloc,
195 A2: UsmAlloc,
196 {
197 assert_eq!(
198 src.get_len(),
199 dst.get_len(),
200 "source and destination array lengths differ"
201 );
202
203 let dep_events = dep_events
205 .iter()
206 .map(|e| EventPtr {
207 ptr: (*e).clone().0,
208 })
209 .collect::<Vec<_>>();
210
211 let num_bytes = src.get_len() * size_of::<T>();
212 unsafe {
213 ffi::memcpy(
214 &mut self.0,
215 dst.get_byte_ptr(),
216 src.get_byte_ptr(),
217 num_bytes,
218 dep_events,
219 )
220 }
221 .map(Into::into)
222 }
223}
224
225impl From<&Device> for Queue {
226 fn from(value: &Device) -> Self {
227 Self(ffi::new_queue_from_device(&value.0))
228 }
229}
230
231impl From<(&Context, &Device)> for Queue {
232 fn from(value: (&Context, &Device)) -> Self {
233 Self(ffi::new_queue_from_context_and_device(
234 &value.0.0, &value.1.0,
235 ))
236 }
237}
238
239impl From<cxx::UniquePtr<ffi::Queue>> for Queue {
240 fn from(value: cxx::UniquePtr<ffi::Queue>) -> Self {
241 Self(value)
242 }
243}
244
245impl Clone for Queue {
246 fn clone(&self) -> Self {
247 ffi::clone(&self.0).into()
248 }
249}